IClaimsTransformation 用来对由我们的应用程序传入的 ClaimsPrincipal 进行转换,它只定义了一个 Transform 方法:
public interface IClaimsTransformation { Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal); }其默认实现,不做任何处理,直接返回。它适合于全局的为 ClaimsPrincipal 添加一些预定义的声明,如添加当前时间等,然后在DI中把我们的实现注册进去即可。
Usage下面我们演示一下 ASP.NET Core 认证系统的实际用法:
首先,我们要定义一个Handler:
public class MyHandler : IAuthenticationHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler { public AuthenticationScheme Scheme { get; private set; } protected HttpContext Context { get; private set; } public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) { Scheme = scheme; Context = context; return Task.CompletedTask; } public async Task<AuthenticateResult> AuthenticateAsync() { var cookie = Context.Request.Cookies["mycookie"]; if (string.IsNullOrEmpty(cookie)) { return AuthenticateResult.NoResult(); } return AuthenticateResult.Success(Deserialize(cookie)); } public Task ChallengeAsync(AuthenticationProperties properties) { Context.Response.Redirect("/login"); return Task.CompletedTask; } public Task ForbidAsync(AuthenticationProperties properties) { Context.Response.StatusCode = 403; return Task.CompletedTask; } public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) { var ticket = new AuthenticationTicket(user, properties, Scheme.Name); Context.Response.Cookies.Append("myCookie", Serialize(ticket)); return Task.CompletedTask; } public Task SignOutAsync(AuthenticationProperties properties) { Context.Response.Cookies.Delete("myCookie"); return Task.CompletedTask; } }如上,在 SignInAsync 中将用户的Claim序列化后保存到Cookie中,在 AuthenticateAsync 中从Cookie中读取并反序列化成用户Claim。
然后在DI系统中注册我们的Handler和Scheme:
public void ConfigureServices(IServiceCollection services) { services.AddAuthenticationCore(options => options.AddScheme<MyHandler>("myScheme", "demo scheme")); }最后,便可以通过HttpContext来调用认证系统了:
public void Configure(IApplicationBuilder app) { // 登录 app.Map("/login", builder => builder.Use(next => { return async (context) => { var claimIdentity = new ClaimsIdentity(); claimIdentity.AddClaim(new Claim(ClaimTypes.Name, "jim")); await context.SignInAsync("myScheme", new ClaimsPrincipal(claimIdentity)); }; })); // 退出 app.Map("/logout", builder => builder.Use(next => { return async (context) => { await context.SignOutAsync("myScheme"); }; })); // 认证 app.Use(next => { return async (context) => { var result = await context.AuthenticateAsync("myScheme"); if (result?.Principal != null) context.User = result.Principal; await next(context); }; }); // 授权 app.Use(async (context, next) => { var user = context.User; if (user?.Identity?.IsAuthenticated ?? false) { if (user.Identity.Name != "jim") await context.ForbidAsync("myScheme"); else await next(); } else { await context.ChallengeAsync("myScheme"); } }); // 访问受保护资源 app.Map("/resource", builder => builder.Run(async (context) => await context.Response.WriteAsync("Hello, ASP.NET Core!"))); }在这里完整演示了 ASP.NET Core 认证系统的基本用法,当然,在实际使用中要比这更加复杂,如安全性,易用性等方面的完善,但本质上也就这么多东西。
总结本章基于 HttpAbstractions 对 ASP.NET Core 认证系统做了一个简单的介绍,但大多是一些抽象层次的定义,并未涉及到具体的实现。因为现实中有各种各样的场景无法预测,HttpAbstractions 提供了统一的认证规范,在我们的应用程序中,可以根据具体需求来灵活的扩展适合的认证方式。不过在 Security 提供了更加具体的实现方式,也包含了 Cookie, JwtBearer, OAuth, OpenIdConnect 等较为常用的认证实现。在下个系列会来详细介绍一下 ASP.NET Core 的认证与授权,更加偏向于实战,敬请期待!
ASP.NET Core 在GitHub上的开源地址为:https://github.com/aspnet,包含了100多个项目,ASP.NET Core 的核心是 HttpAbstractions ,其它的都是围绕着 HttpAbstractions 进行的扩展。本系列文章所涉及到的源码只包含 Hosting 和 HttpAbstractions ,它们两个已经构成了一个完整的 ASP.NET Core 运行时,不需要其它模块,就可以轻松应对一些简单的场景。当然,更多的时候我们还会使用比较熟悉的 Mvc 来大大提高开发速度和体验,后续再来介绍一下MVC的运行方式。
posted @