为什么我应该始终为我的 Authorize 属性定义 JwtBearerDefaults.AuthenticationScheme?

Why should I define JwtBearerDefaults.AuthenticationScheme for my Authorize attribute always?

我有一个 JWT 身份验证的简单示例,您可以找到它 here

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>

如您所见,我已将 JwtBearerDefaults.AuthenticationScheme 添加到 Startup/ConfigureServices 方法中的 Authentication 中,因此我应该能够独立使用 [Authorize] 如下

[Authorize]
public sealed class WeatherForecastController : BaseController
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

但我不知道为什么它不起作用! (我已经用 Postman 测试过)。我必须通过AuthenticationSchemes定义它。

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public sealed class WeatherForecastController : BaseController
{
    private static readonly string[] Summaries = new[]
    {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

任何人都可以指导我如何使用 Authorize 属性独立 而没有 AuthenticationSchemes 特别是当我在 ConfigureServices 中定义它时?我哪里设置错了?

您的代码没有包含 app.UseAuthentication()。所以这意味着没有身份验证中间件。

默认身份验证方案仅由身份验证中间件用于自动验证请求并建立当前主体。当您单独使用 [Authorize] 时,不会设置身份验证方案,并且授权过滤器将不起作用。由 IAuthorizeDataAuthorizeAttribute 是一个 IAuthorizeData)构建的过滤器是一个 AuthorizeFilter,这需要显式设置方案。

这就是为什么其他 [Authorize(...)] 具有某些方案集但不能 [Authorize] 的原因。

所以你应该使用身份验证中间件来方便地使用[Authorize]而不需要指定方案

AuthorizeFilter 将在内部使用 IPolicyEvaluator 来验证请求,这里是 PolicyEvaluator.AuthenticateAsync 的默认实现 - 您可以看到它检查 AuthenticationSchemes 的可用性。

在 .NET 5 中,您可以配置如下:

AddJwtBearer

中添加 JwtBearerDefaults.AuthenticationScheme 作为默认方案字符串
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
      .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwt =>
       {
         jwt.TokenValidationParameters = new TokenValidationParameters
           {
             ValidateIssuer = true,
                       ....
            ;
                
         });

在 Configure 中使用(如果也使用 Role)

  app.UseAuthentication();
  app.UseAuthorization();

然后您可以使用 [Authorired] 属性作为默认值

[ApiController]
[Route("api/data")]
[Authorize]
public class DataController : ControllerBase

AddIdentityCore() 和 AddIdentity() 方法之间也存在冲突。如果您使用 AddIdentity,它会使用基于 Cookie 的身份验证,因此如果您不明确编写 [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)],JWT 将无法工作。我如下更改了我的启动,现在它与 .Net 6 中的 [Authorize] 一起使用。我正在为用户和角色使用自定义 类。

services.AddIdentityCore<AppUser>(x =>
{
    x.Password.RequireDigit = false;
    x.Password.RequiredLength = 4;
    x.Password.RequireLowercase = false;
    x.Password.RequireNonAlphanumeric = false;
    x.Password.RequireUppercase = false;
})
.AddRoles<AppRole>()
.AddEntityFrameworkStores<DBContext>();