认证(Authentication)和授权(Authorization)是两个不同的动作

  • 认证主要判断请求是由谁发出的,确认请求用户的信息(Claims,类似身份证信息的概念)
  • 授权是在认证的基础上,根据认证获取到的用户的信息,判断用户是否有其请求资源的操作权限

认证

  1. services.AddAuthentication(), app.UseAuthentication()配置使用认证中间件
  2. 添加认证中间件时,可以设置多种不同的认证方案(Scheme)
  3. 常见的一些认证方案&自定义
    • CookieAuthenticationDefaults.AuthenticationScheme
      services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    • JwtBearerDefaults.AuthenticationScheme
      services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    • IdentityConstants.ApplicationScheme
      services.AddIdentity<IdentityUser, IdentityRole>()
      AddIdentity里面做了一个如下的操作
      services.AddAuthentication(options =>
      {
          options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
          options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
          options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
      })
    • 自定义认证方案
      services.AddAuthentication("CustomAuth");
      //或者
      services.AddAuthentication(options =>
      {
          options.DefaultAuthenticateScheme = "CustomAuth";
          options.DefaultChallengeScheme = "CustomAuth";//也可以指定成其他的,不一定要和DefaultAuthenticateScheme一样
          options.DefaultSignInScheme = "CustomAuth";//也可以指定成其他的,不一定要和DefaultAuthenticateScheme一样
      })
  4. 只设置认证方案是不够的,还需要对认证方案指定验证逻辑(AuthenticationHandler)
  5. 常见的一些认证方案指定验证逻辑
    • CookieAuthenticationDefaults.AuthenticationScheme -> CookieAuthenticationHandler
      //https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Cookies/src/CookieExtensions.cs
      services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options=>{xxx});
    • JwtBearerDefaults.AuthenticationScheme -> JwtBearerHandler
      //https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/JwtBearer/src/JwtBearerExtensions.cs
      services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options=>{xxx})
    • IdentityConstants.ApplicationScheme -> CookieAuthenticationHandler (阅读理解services.AddIdentity源码)
      services.AddAuthentication(options =>
      {
          options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
          options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
          options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
      })
      //对IdentityConstants.ApplicationScheme认证方案指定CookieAuthenticationHandler
      .AddCookie(IdentityConstants.ApplicationScheme, o =>
      {
          o.LoginPath = new PathString("/Account/Login");
          o.Events = new CookieAuthenticationEvents
          {
              OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
          };
      })
      //对IdentityConstants.ExternalScheme认证方案指定CookieAuthenticationHandler
      .AddCookie(IdentityConstants.ExternalScheme, o =>
      {
          o.Cookie.Name = IdentityConstants.ExternalScheme;
          o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
      })
      //对IdentityConstants.TwoFactorRememberMeScheme认证方案指定CookieAuthenticationHandler
      .AddCookie(IdentityConstants.TwoFactorRememberMeScheme, o =>
      {
          o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme;
          o.Events = new CookieAuthenticationEvents
          {
              OnValidatePrincipal = SecurityStampValidator.ValidateAsync<ITwoFactorSecurityStampValidator>
          };
      })
      //对IdentityConstants.TwoFactorUserIdScheme认证方案指定CookieAuthenticationHandler
      .AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
      {
          o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
          o.Events = new CookieAuthenticationEvents
          {
              OnRedirectToReturnUrl = _ => Task.CompletedTask
          };
          o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
      });
    • 自定义认证方案
      • 定义一个类继承AuthenticationHandler,重写HandleAuthenticateAsync方法
      • 定义一个类继承AuthenticationSchemeOptions
      • 定义一个AuthenticationBuilder的扩展方法,例如:
        public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthenticationOptions> configureOptions)
        {
            return builder.AddScheme<CustomAuthenticationOptions, CustomAuthenticationHandler>("CustomAuth", configureOptions);
        }
      • 指定验证逻辑
        services.AddAuthentication("CustomAuth").AddCustomAuth(options=>{xxx});
  6. 认证方案和验证逻辑是可以任意组合绑定的,例如:CookieAuthenticationDefaults.AuthenticationSchemeIdentityConstants.ApplicationScheme,都会指定用CookieAuthenticationHandler

授权

  1. 要在app.UseAuthentication()代码之后添加app.UseAuthorization()使用授权中间件
  2. 使用AuthorizeAttribute特性标记控制器类或方法需要的权限
    [Authorize]//不指定认证方案,会按默认的认证方案处理
    [Authorize(AuthenticationSchemes="CustomAuth")]//指定用特定的认证方案
    [Authorize("AtLeast21")]//基于Policy授权
    [Authorize(Policy="AtLeast21")]//基于Policy授权
    [Authorize(Roles="Admin")]//基于角色授权
  3. 直接对终结点设置需要的权限
    app.UseEndpoints(endpoints =>
    {
        var pipeline = endpoints.CreateApplicationBuilder().Build();
        var swaggerAuthAttr = new AuthorizeAttribute("swagger-permission");
        endpoints.Map("/swagger/{documentName}/swagger.json", pipeline).RequireAuthorization(swaggerAuthAttr);
        endpoints.Map("/swagger/index.html", pipeline).RequireAuthorization(swaggerAuthAttr);
        endpoints.Map("/myswagger/{documentName}/swagger.json", pipeline).RequireAuthorization(swaggerAuthAttr);
        endpoints.Map("/myswagger/index.html", pipeline).RequireAuthorization(swaggerAuthAttr);
    });
  4. 基于Policy授权
  5. 基于角色授权