授权策略属性始终 returns 403 禁止使用 .net 核心身份和 JwtBearerAuthentication
Authorize Policy attribute always returns 403 forbidden using .net core Identity and JwtBearerAuthentication
在 this guide 之后,我能够使用
进行身份验证
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.AspNetCore.Authentication.JwtBearer
现在我正在尝试使用角色或声明来保护我的 api 端点。我都试过了,结果相同 (403)
仅使用 [Authorize]
即可。
我的代码目前看起来像这样:
Controller:
[Authorize(Policy = "RequireUserRole")]
// Also tried [Authorize(Roles="User")]
public string Get()
{
return "YO";
}
Startup:
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");
角色关系创建成功,但到达端点时对角色的验证失败。
感谢任何帮助!
答案就在这个mdsn blog post:
Authorizing based on roles is available out-of-the-box with ASP.NET
Identity. As long as the bearer token used for authentication contains
a roles element, ASP.NET Core’s JWT bearer authentication middleware
will use that data to populate roles for the user.
So, a roles-based authorization attribute (like [Authorize(Roles =
"Manager,Administrator")] to limit access to managers and admins) can
be added to APIs and work immediately.
所以我在我的访问令牌对象中添加了一个名为角色的元素:
private string GetAccessToken(string userRole)
{
var payload = new Dictionary<string, object>
{
...
{ "roles", userRole }
};
return GetToken(payload);
}
我阅读了那个 msdn post 并在启动时添加了:
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 header:
[HttpGet("TestAuth")]
[Authorize(Policy = "Test")]
public IActionResult TestAuth()
{
return new OkResult();
}
在 this guide 之后,我能够使用
进行身份验证Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.AspNetCore.Authentication.JwtBearer
现在我正在尝试使用角色或声明来保护我的 api 端点。我都试过了,结果相同 (403)
仅使用 [Authorize]
即可。
我的代码目前看起来像这样:
Controller:
[Authorize(Policy = "RequireUserRole")]
// Also tried [Authorize(Roles="User")]
public string Get()
{
return "YO";
}
Startup:
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");
角色关系创建成功,但到达端点时对角色的验证失败。
感谢任何帮助!
答案就在这个mdsn blog post:
Authorizing based on roles is available out-of-the-box with ASP.NET Identity. As long as the bearer token used for authentication contains a roles element, ASP.NET Core’s JWT bearer authentication middleware will use that data to populate roles for the user.
So, a roles-based authorization attribute (like [Authorize(Roles = "Manager,Administrator")] to limit access to managers and admins) can be added to APIs and work immediately.
所以我在我的访问令牌对象中添加了一个名为角色的元素:
private string GetAccessToken(string userRole)
{
var payload = new Dictionary<string, object>
{
...
{ "roles", userRole }
};
return GetToken(payload);
}
我阅读了那个 msdn post 并在启动时添加了:
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 header:
[HttpGet("TestAuth")]
[Authorize(Policy = "Test")]
public IActionResult TestAuth()
{
return new OkResult();
}