【问题标题】:Authorize Policy attribute always returns 403 forbidden using .net core Identity and JwtBearerAuthenticationAuthorize Policy 属性总是返回 403 禁止使用 .net core Identity 和 JwtBearerAuthentication
【发布时间】:2017-11-17 06:12:26
【问题描述】:

this guide 之后,我能够使用

进行身份验证
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.AspNetCore.Authentication.JwtBearer

现在我正在尝试使用角色或声明来保护我的 api 端点。我都试过了,结果相同(403)

仅使用 [Authorize] 即可。

我的代码目前看起来像这样:

控制器:

[Authorize(Policy = "RequireUserRole")]
// Also tried [Authorize(Roles="User")]
public string Get()
{   
  return "YO";
}

启动:

services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<ApplicationContext>();
services.Configure<JWTSettings>(Configuration.GetSection("JWTSettings"));
services.AddAuthorization(options =>
{
        options.AddPolicy("RequireUserRole", policy => policy.RequireRole("User"));
});

...

app.UseIdentity();

var secretKey = Configuration.GetSection("JWTSettings:SecretKey").Value;
var issuer = Configuration.GetSection("JWTSettings:Issuer").Value;
var audience = Configuration.GetSection("JWTSettings:Audience").Value;
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        TokenValidationParameters = new TokenValidationParameters
        {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,

                // Validate the JWT Issuer (iss) claim
                ValidateIssuer = true,
                ValidIssuer = issuer,

                // Validate the JWT Audience (aud) claim
                ValidateAudience = true,
                ValidAudience = audience,

                ValidateLifetime = true
        }
});

app.UseMvcWithDefaultRoute();

当我创建用户时,我将其分配给角色“用户”

await _userManager.AddToRoleAsync(user, "User");

角色关系创建成功,但到达端点时角色验证失败。

任何帮助表示赞赏!

【问题讨论】:

  • 对我来说值得注意的是 .RequrieClaim("role", "admin") 不起作用,.RequireRole("admin") 这样做了,感谢您给了我尝试的想法
  • 我不得不为 Azure 应用程序授权更改角色声明类型:options.TokenValidationParameters.RoleClaimType = "schemas.microsoft.com/ws/2008/06/identity/claims/role";

标签: asp.net asp.net-core asp.net-identity jwt claims-based-identity


【解决方案1】:

答案就在这个mdsn blog post

基于角色的授权可通过 ASP.NET 开箱即用 身份。只要用于身份验证的不记名令牌包含 角色元素,ASP.NET Core 的 JWT 不记名身份验证中间件 将使用该数据为用户填充角色。

因此,基于角色的授权属性(如 [Authorize(Roles = "Manager,Administrator")] 来限制对管理员和管理员的访问) 可以 被添加到 API 并立即工作。

所以我在我的访问令牌对象中添加了一个名为角色的元素:

private string GetAccessToken(string userRole)
{
    var payload = new Dictionary<string, object>
    {
        ...
        { "roles", userRole } 
    };
    return GetToken(payload);
}

【讨论】:

  • 我认为这在系统中是一种不好的做法,您可能会更改用户角色,并且用户之前登录过一次并且过期时间很长。
【解决方案2】:

我阅读了那个 msdn 帖子并在启动时添加了:

   internal class HasRoleRequerementAuthHandler : AuthorizationHandler<HasRoleRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasRoleRequirement requirement)
    { 

        if (context.User.HasClaim(c => c.Type == JwtRegisteredClaimNames.NameId))
            if (context.User.FindFirst(c => c.Type == JwtRegisteredClaimNames.Typ).Value == requirement.RoleName)
                context.Succeed(requirement);
        return Task.CompletedTask;

    }
}    
internal class HasRoleRequirement : IAuthorizationRequirement
{
    public readonly string RoleName;

    public HasRoleRequirement(string roleName)
    {
        RoleName = roleName;
    }
}

然后添加策略:

       opt.AddPolicy("Test", builder =>
            {
                builder.Requirements.Add(new HasRoleRequirement("User"));
            });

我的令牌是这样生成的:

        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.NameId, user.Uid),
            new Claim(JwtRegisteredClaimNames.Typ, type.ToString())
        };


        var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature);

        var tokenDesc = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(claims),
            Expires = DateTime.Now.AddDays(7),
            SigningCredentials = creds
        };

        var tokenHandler = new JwtSecurityTokenHandler();

        var token = tokenHandler.CreateToken(tokenDesc);
        return tokenHandler.WriteToken(token);

然后我可以使用策略 Auth 标头:

    [HttpGet("TestAuth")]
    [Authorize(Policy = "Test")]
    public IActionResult TestAuth()
    {
        return new OkResult();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2018-10-24
    • 1970-01-01
    • 2020-12-01
    相关资源
    最近更新 更多