理解ASP.NET Core验证模型 - zLulus/My_Note GitHub Wiki

概念

转载自:https://www.cnblogs.com/dudu/p/6367303.html

ASP.NET Core 的验证模型是 claims-based authentication 。Claim 是对被验证主体特征的一种表述,比如:登录用户名是...,email是...,用户Id是...,其中的“登录用户名”,“email”,“用户Id”就是ClaimType。

You can think of claims as being a statement about...That statement consists of a name and a value.   

对应现实中的事物,比如驾照,驾照中的“身份证号码:xxx”是一个claim,“姓名:xxx”是另一个claim。

一组claims构成了一个identity,具有这些claims的identity就是 ClaimsIdentity ,驾照就是一种ClaimsIdentity,可以把ClaimsIdentity理解为“证件”,驾照是一种证件,护照也是一种证件。

ClaimsIdentity的持有者就是 ClaimsPrincipal ,一个ClaimsPrincipal可以持有多个ClaimsIdentity,就比如一个人既持有驾照,又持有护照。

理解了Claim, ClaimsIdentity, ClaimsPrincipal这三个概念,就能理解生成登录Cookie为什么要用下面的代码?

var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, loginName) }, "Basic");
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
await context.Authentication.SignInAsync(_cookieAuthOptions.AuthenticationScheme, claimsPrincipal);

要用Cookie代表一个通过验证的主体,必须包含Claim, ClaimsIdentity, ClaimsPrincipal这三个信息,以一个持有合法驾照的人做比方,ClaimsPrincipal就是持有证件的人,ClaimsIdentity就是证件,"Basic"就是证件类型(这里假设是驾照),Claim就是驾照中的信息。

关键代码

Startup.cs

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddCookie(JwtBearerDefaults.AuthenticationScheme, options =>
            {
                options.LoginPath = "/Home/LogIn";
            });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseJwtTokenMiddleware();
}

UseJwtTokenMiddleware

public static class JwtTokenMiddleware
{
    public static IApplicationBuilder UseJwtTokenMiddleware(this IApplicationBuilder app, string schema = JwtBearerDefaults.AuthenticationScheme)
    {
        return app.Use(async (ctx, next) =>
        {
            if (ctx.User.Identity?.IsAuthenticated != true)
            {
                var result = await ctx.AuthenticateAsync(schema);
                if (result.Succeeded && result.Principal != null)
                {
                    ctx.User = result.Principal;
                }
            }

            await next();
        });
    }
}

登录

var loginResult = await _logInManager.LoginAsync(input.UserName, input.Password, GetTenancyNameOrNull());

if (loginResult.Result!= AbpLoginResultType.Success)
{
    throw CreateExceptionForFailedLoginAttempt(loginResult.Result, input.UserName, GetTenancyNameOrNull());
}

var claimsPrincipal = new ClaimsPrincipal(loginResult.Identity);

await HttpContext.SignInAsync(JwtBearerDefaults.AuthenticationScheme,
    claimsPrincipal, new AuthenticationProperties
    {
        IsPersistent = true
    });
await UnitOfWorkManager.Current.SaveChangesAsync();

退出登录

await HttpContext.SignOutAsync(JwtBearerDefaults.AuthenticationScheme);