授权几乎是所以系统都不可或缺的部分,在Nancy中怎么授权呢?我们这篇博文来说一下Nancy的Forms授权。
首先在NuGet上安装Nancy.Authentication.Forms
Nancy的Forms验证得实现IUserMapper接口,用户类实现IUserIdentity接口(为了方便,我把DB的User,Model的User全合成一个User)
User.cs
using Nancy.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestSelfHostWeb
{
public class User : IUserIdentity
{
public User()
{
}
public User(string userName)
{
UserName = userName;
}
/// <summary>
/// 实现接口的成员
/// </summary>
public string UserName
{
get;
set;
}
public string Password
{
get;
set;
}
public string Role
{
get;
set;
}
/// <summary>
/// 这个是Nancy授权中必须的
/// </summary>
public Guid GUID
{
get;
set;
}
/// <summary>
/// 实现接口的成员
/// </summary>
public IEnumerable<string> Claims
{
get;
set;
}
}
}
UserMapper.cs
using Nancy.Authentication.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using Nancy;
using Nancy.Security;
namespace TestSelfHostWeb
{
class UserMapper : IUserMapper
{
//这个用户集合可以来自数据库
static List<User> _users;
static UserMapper()
{
//初始化验用户数据
_users = new List<User>();
_users.Add(new User() { UserName = "aaa", Password = "111111", GUID = new Guid("33e67c06-ed6e-4bd7-a5b0-60ee0fea890c"), Role = "admin" });
_users.Add(new User() { UserName = "bbb", Password = "222222", GUID = new Guid("fba4be7d-25af-416e-a641-a33174f435d1"), Role = "user" });
}
/// <summary>
/// 实现接口的成员,获取用户的角色,以便验证授权
/// </summary>
/// <param name="identifier"></param>
/// <param name="context"></param>
/// <returns></returns>
public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
{
var user = _users.FirstOrDefault(u => u.GUID == identifier);
return user == null
? null
: new User(user.UserName) { Claims = new string[] { user.Role } };
}
/// <summary>
/// 验证用户,验证成功返回用户的GUID,这是规定
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <returns></returns>
public static Guid? ValidateUser(string userName, string password)
{
var user = _users.FirstOrDefault(u => u.UserName == userName && u.Password == password);
if (user == null)
{
return null;
}
return user.GUID;
}
}
}
Bootstrapper.cs
using Nancy;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;
using Nancy.Authentication.Forms;
namespace TestSelfHostWeb
{
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(container, pipelines, context);
//验证配置文件
var formsAuthConfiguration = new FormsAuthenticationConfiguration()
{
RedirectUrl = "~/login",//无验证跳转的路由
UserMapper = container.Resolve<IUserMapper>()//用户对应的Mapper
};
//开启验证
FormsAuthentication.Enable(pipelines, formsAuthConfiguration);
}
}
}
Login.cs
using Nancy;
using Nancy.Authentication.Forms;
using Nancy.ModelBinding;
using System;
namespace TestSelfHostWeb.Modules
{
public class LoginModule : NancyModule
{
public LoginModule()
{
Get["/login"] = parameters =>
{
//用户名和密码验证失败的标识
ViewBag["error"] = Request.Query.error;
return View["login"];
};
Post["/login"] = parameters =>
{
var user = this.Bind<User>();
var guid= UserMapper.ValidateUser(user.UserName, user.Password);
if (guid == null)
{
//按用户名密码查询不到时作的标识
return this.LogoutAndRedirect("~/login?error=true");
}
DateTime? expiry = null;
//登录后跳转页面,必需用户的GUID
return this.LoginAndRedirect(guid.Value, expiry);
};
}
}
}
login.cshtml
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<TestSelfHostWeb.User>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Login</title>
<style type="text/css">
body {
text-align: center;
}
</style>
</head>
<body>
<form action="\Login" method="post">
UserName:<input id="UserName" name="UserName" type="text" />
Password:<input id="Password" name="Password" type="password" />
<input type="submit" value="Login" />
@if (ViewBag["error"])
{
<font color="red">check username or password please</font>
}
</form>
</body>
</html>
Index.cs
using Nancy;
using Nancy.Security;
namespace TestSelfHostWeb.Modules
{
public class IndexModule : NancyModule
{
public IndexModule()
{
//开启全局验证
this.RequiresAuthentication();
Get["/"] = parameters =>
{
//开启角色验证,只有该角色可以访问本路由
this.RequiresClaims("admin");
return View["index"];
};
}
}
}
Index.cshtml同上篇的indexx.cshtml
到了test的时刻了
启动host(注意以管理员身份运行)
访问网站的主页,如下图,会跳转到登记页,这是因为index.cs的IndexModule中开启了this.RequiresAuthentication()验证,为什么会跳转到login路由中呢,是因为Bootstrapper中formAuthConfiguration中的RedirectUrl设置。
如果用户名或密码错误 ,会得到提示:
如果用户名密码正确:
如果不具备权限的人(UserName:bbb,Passowrd:222222)登录,会报403错误(这个不太友下,下篇博客解决)
这样就能轻量级的按解色来授权我们的系统了。
来源:oschina
链接:https://my.oschina.net/u/4288691/blog/4317460