你的位置:首页 > ASP.net教程

[ASP.net教程]Nancy FormsAuthentication使用

1、新建UserDatabase类,实现IUserMapper接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;

using Nancy.Authentication.Forms;

public class UserDatabase : IUserMapper
{
private static List<Tuple<string, string, Guid>> users = new List<Tuple<string, string, Guid>>();

static UserDatabase()
{
users.Add(new Tuple<string, string, Guid>("admin", "password", new Guid("55E1E49E-B7E8-4EEA-8459-7A906AC4D4C0")));
users.Add(new Tuple<string, string, Guid>("user", "password", new Guid("56E1E49E-B7E8-4EEA-8459-7A906AC4D4C0")));
}

public ClaimsPrincipal GetUserFromIdentifier(Guid identifier, NancyContext context)
{
var userRecord = users.FirstOrDefault(u => u.Item3 == identifier);

return userRecord == null
? null
: new ClaimsPrincipal(new ClaimsIdentity(BuildClaims(userRecord.Item1), "querystring"));
}

public static Guid? ValidateUser(string username, string password)
{
var userRecord = users.FirstOrDefault(u => u.Item1 == username && u.Item2 == password);

if (userRecord == null)
{
return null;
}

return userRecord.Item3;
}

/// <summary>
/// Build claims based on username
/// </summary>
/// <param name="userName">Current username</param>
/// <returns>IEnumerable of claims</returns>
private static IEnumerable<Claim> BuildClaims(string userName)
{
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Role, userName));
return claims;
}
}

2、新建FormsAuthBootstrapper启动类

using Nancy.Authentication.Forms;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;

public class FormsAuthBootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
// We don't call "base" here to prevent auto-discovery of
// types/dependencies
}

protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{
base.ConfigureRequestContainer(container, context);

// Here we register our user mapper as a per-request singleton.
// As this is now per-request we could inject a request scoped
// database "context" or other request scoped services.
container.Register<IUserMapper, UserDatabase>();
}

protected override void RequestStartup(TinyIoCContainer requestContainer, IPipelines pipelines, NancyContext context)
{
// At request startup we modify the request pipelines to
// include forms authentication - passing in our now request
// scoped user name mapper.
//
// The pipelines passed in here are specific to this request,
// so we can add/remove/update items in them as we please.
var formsAuthConfiguration =
new FormsAuthenticationConfiguration()
{
RedirectUrl = "~/login",
UserMapper = requestContainer.Resolve<IUserMapper>(),
};

FormsAuthentication.Enable(pipelines, formsAuthConfiguration);
}
}

3、登录方法实现

Post["/login"] = x => {
var userGuid = UserDatabase.ValidateUser((string)this.Request.Form.Username, (string)this.Request.Form.Password);

if (userGuid == null)
{
return this.Context.GetRedirect("~/login?error=true&username=" + (string)this.Request.Form.Username);
}

DateTime? expiry = null;
if (this.Request.Form.RememberMe.HasValue)
{
expiry = DateTime.Now.AddDays(7);
}

return this.LoginAndRedirect(userGuid.Value, expiry);
};

4、需要授权地方使用

Get["/secured"] = x => {
this.RequiresAuthentication();//需要登录才能访问,否则返回bootstrap配置中的地址。
this.RequiresClaims(c => c.Type == ClaimTypes.Role && c.Value == "admin");//申明了admin的角色才可访问,否则403

//this.RequiresAnyClaim(h=>h.Value== "admin"||h.Value=="User"); //申明值为admin或user的均可访问,否则403

var model = new UserModel(this.Context.CurrentUser.Identity.Name);
return View["secure.cshtml", model];
};