带有JWT的.NET Core 3.1基于角色的授权禁止返回403

问题描述

我遇到一个问题,当我尝试在控制器中使用[Authorize(Roles = "Administrator")]时,它总是返回403。我正在使用身份和JWT令牌。这是我的Startup.cs。我在app.UseAuthentication()中同时呼叫app.UseAuthorization()ConfigureServices(),但每次返回403

时都一样
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddIdentity<User,Role>(options =>
    {
        options.Password.requiredigit = false;
        options.Password.RequireLowercase = false;
        options.Password.RequireNonAlphanumeric = false;
        options.Password.RequireUppercase = false;
        options.Password.requiredUniqueChars = 0;
        options.Password.requiredLength = 6;

        options.Cla@R_502[email protected]aimType = "user_id";
        options.Cla@R_502[email protected]aimType = "email";
        options.Cla@R_502[email protected]aimType = "user_role";
    })
        .AddRoles<Role>()
        .AddEntityFrameworkStores<MyDbContext>()
        .AddDefaultTokenProviders();

    var key = Encoding.UTF8.GetBytes(Configuration["ApplicationSettings:JwtKey"].ToString());

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options => {
        options.RequireHttpsMetadata = false;
        options.Savetoken = false;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,ValidateAudience = false,ValidateIssuer = false,IssuerSigningKey = new SymmetricSecurityKey(key),ClockSkew = TimeSpan.Zero
        };

        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;

                return Task.CompletedTask;
            }
        };
    });

    services.AddControllers()
        .AddNewtonsoftJson(options =>
        {
            options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });
...
}

public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthentication();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

这是我创建令牌的方式

private async Task<string> Generatetoken(DataModelUser user)
{
    var key = Encoding.UTF8.GetBytes(_appSettings.JwtKey);
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new Cla@R_502_6424@Identity(new Claim[]
        {
            new Claim("user_role",user.Role.ToString()),new Claim("user_id",user.Id.ToString()),new Claim("email",user.Email)
        }),Expires = DateTime.UtcNow.AddDays(1),SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),SecurityAlgorithms.HmacSha256Signature)
    };

    var tokenHandler = new JwtSecurityTokenHandler();
    var securityToken = tokenHandler.Createtoken(tokenDescriptor);

    return tokenHandler.Writetoken(securityToken);
}

我在控制器上添加了这样的内容

[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ProfileController : ControllerBase
{
    [HttpGet]
    [Authorize(Roles = "Administrator")]
    public async Task<IActionResult> Get()
    {
        return Ok();
    }
}

这是我的JWT令牌有效载荷!

{
  "user_role": "Administrator","user_id": "5a6333f1-9696-4b1c-a8f8-04619ebd686d","name": "Admin Admin","completed_profile": "False","email": "myadmine[email protected]","nbf": 1597147248,"exp": 1597233648,"iat": 1597147248
}

解决方法

我遇到了类似的问题,我通过在TokenValidationParameter中添加RoleClaimType和NameClaimType来解决了该问题:

options.TokenValidationParameters = new TokenValidationParameters
{
    ValidateIssuerSigningKey = true,ValidateAudience = false,ValidateIssuer = false,IssuerSigningKey = new SymmetricSecurityKey(key),ClockSkew = TimeSpan.Zero,RoleClaimType = IdentityModel.JwtClaimTypes.Role,NameClaimType = IdentityModel.JwtClaimTypes.Name
};