授权策略属性始终使用.net核心标识和JwtBearerAuthentication返回403禁止

时间:2017-06-14 22:41:52

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

关注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();

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

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

正在成功创建角色关系,但在点击端点时对角色的验证失败。

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:7)

答案在mdsn blog post

  

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

     

所以,一个基于角色的授权属性(如[Authorize(Roles =   &#34;经理,管理员&#34;)]限制对经理和管理员的访问权限)   添加到API并立即工作。

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

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

答案 1 :(得分:0)

我阅读了该msdn帖子,并在启动时添加了它:

static void AddToArray(string[,] result, string[,] array, int start = 0)
{
    for (int i = 0; i < array.GetLength(0); ++i)
    {
        for (int j = 0; j < array.GetLength(1); ++j)
        {
            result[i + start, j] = array[i, j];
        }
    }
}

string[,] Classroom1 = {
                {"John", "16"},
                {"Ethan","18"},
                {"Jake", "17"}
            };

string[,] Classroom2 = {
                {"Jeff", "17"},
                {"Tom","16"},
                {"Jay", "18"}
            };

int d1 = Classroom1.GetLength(0) + Classroom2.GetLength(0);
int d2 = Classroom1.GetLength(1) > Classroom2.GetLength(1) ? Classroom1.GetLength(1) : Classroom2.GetLength(1);
string[,] result = new string[d1, d2];

AddToArray(result, Classroom1);
AddToArray(result, Classroom2, Classroom1.GetLength(0));

for (int i = 0; i < result.GetLength(0); ++i)
{
    for (int j = 0; j < result.GetLength(1); ++j)
    {
        Console.Write(result[i, j] + " ");
    }
    Console.WriteLine();
}

然后添加了政策:

export type PrependArray<Val, T> = T extends [
    infer A,
    infer B,
    infer C,
    infer D,
    infer E,
    infer F,
    infer G,
    infer H,
    infer I,
    infer J
]
    ? [Val, A, B, C, D, E, F, G, H, I, J]
    : T extends [infer A, infer B, infer C, infer D, infer E, infer F, infer G, infer H, infer I]
    ? [Val, A, B, C, D, E, F, G, H, I]
    : T extends [infer A, infer B, infer C, infer D, infer E, infer F, infer G, infer H]
    ? [Val, A, B, C, D, E, F, G, H]
    : T extends [infer A, infer B, infer C, infer D, infer E, infer F, infer G]
    ? [Val, A, B, C, D, E, F, G]
    : T extends [infer A, infer B, infer C, infer D, infer E, infer F]
    ? [Val, A, B, C, D, E, F]
    : T extends [infer A, infer B, infer C, infer D, infer E]
    ? [Val, A, B, C, D, E]
    : T extends [infer A, infer B, infer C, infer D]
    ? [Val, A, B, C, D]
    : T extends [infer A, infer B, infer C]
    ? [Val, A, B, C]
    : T extends [infer A, infer B]
    ? [Val, A, B]
    : T extends [infer A]
    ? [Val, A]
    : ArrayWrap<Val>;

我的令牌是这样生成的:

   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;
    }
}

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

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