ASP.NET Core JWT 映射角色声明到 ClaimsIdentity [英] ASP.NET Core JWT mapping role claims to ClaimsIdentity
问题描述
我想使用 JWT 保护 ASP.NET Core Web API.此外,我希望可以选择直接在控制器操作属性中使用令牌负载中的角色.
I want to protect ASP.NET Core Web API using JWT. Additionally, I would like to have an option of using roles from tokens payload directly in controller actions attributes.
现在,虽然我确实找到了如何将它与策略一起使用:
Now, while I did find it out how to use it with Policies:
Authorize(Policy="CheckIfUserIsOfRoleX")
ControllerAction()...
我更希望有一个选项来使用通常的东西:
I would like better to have an option to use something usual like:
Authorize(Role="RoleX")
从 JWT 负载自动映射角色的位置.
where Role would be automatically mapped from JWT payload.
{
name: "somename",
roles: ["RoleX", "RoleY", "RoleZ"]
}
那么,在 ASP.NET Core 中完成此任务的最简单方法是什么?有没有办法通过一些设置/映射自动使其工作(如果是,在哪里设置?)或者我应该在验证令牌后拦截 ClaimsIdentity
的生成并手动添加角色声明(如果是这样,在哪里/如何做到这一点?)?
So, what is the easiest way to accomplish this in ASP.NET Core? Is there a way to get this working automatically through some settings/mappings (if so, where to set it?) or should I, after token is validated, intercept generation of ClaimsIdentity
and add roles claims manually (if so, where/how to do that?)?
推荐答案
生成 JWT 时需要获取有效声明.这是示例代码:
You need get valid claims when generating JWT. Here is example code:
登录逻辑:
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody] ApplicationUser applicationUser) {
var result = await _signInManager.PasswordSignInAsync(applicationUser.UserName, applicationUser.Password, true, false);
if(result.Succeeded) {
var user = await _userManager.FindByNameAsync(applicationUser.UserName);
// Get valid claims and pass them into JWT
var claims = await GetValidClaims(user);
// Create the JWT security token and encode it.
var jwt = new JwtSecurityToken(
issuer: _jwtOptions.Issuer,
audience: _jwtOptions.Audience,
claims: claims,
notBefore: _jwtOptions.NotBefore,
expires: _jwtOptions.Expiration,
signingCredentials: _jwtOptions.SigningCredentials);
//...
} else {
throw new ApiException('Wrong username or password', 403);
}
}
获取基于UserRoles
、RoleClaims
和UserClaims
表(ASP.NET Identity)的用户声明:
Get user claims based UserRoles
, RoleClaims
and UserClaims
tables (ASP.NET Identity):
private async Task<List<Claim>> GetValidClaims(ApplicationUser user)
{
IdentityOptions _options = new IdentityOptions();
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
new Claim(_options.ClaimsIdentity.UserIdClaimType, user.Id.ToString()),
new Claim(_options.ClaimsIdentity.UserNameClaimType, user.UserName)
};
var userClaims = await _userManager.GetClaimsAsync(user);
var userRoles = await _userManager.GetRolesAsync(user);
claims.AddRange(userClaims);
foreach (var userRole in userRoles)
{
claims.Add(new Claim(ClaimTypes.Role, userRole));
var role = await _roleManager.FindByNameAsync(userRole);
if(role != null)
{
var roleClaims = await _roleManager.GetClaimsAsync(role);
foreach(Claim roleClaim in roleClaims)
{
claims.Add(roleClaim);
}
}
}
return claims;
}
在Startup.cs
中,请在授权中添加需要的策略:
In Startup.cs
please add needed policies into authorization:
void ConfigureServices(IServiceCollection service) {
services.AddAuthorization(options =>
{
// Here I stored necessary permissions/roles in a constant
foreach (var prop in typeof(ClaimPermission).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy))
{
options.AddPolicy(prop.GetValue(null).ToString(), policy => policy.RequireClaim(ClaimType.Permission, prop.GetValue(null).ToString()));
}
});
}
声明权限:
public static class ClaimPermission
{
public const string
CanAddNewService = "Tự thêm dịch vụ",
CanCancelCustomerServices = "Hủy dịch vụ khách gọi",
CanPrintReceiptAgain = "In lại hóa đơn",
CanImportGoods = "Quản lý tồn kho",
CanManageComputers = "Quản lý máy tính",
CanManageCoffees = "Quản lý bàn cà phê",
CanManageBillards = "Quản lý bàn billard";
}
使用类似的代码段获取所有预定义的权限并将其插入到 asp.net 权限声明表中:
Use the similar snippet to get all pre-defined permissions and insert it to asp.net permission claims table:
var staffRole = await roleManager.CreateRoleIfNotExists(UserType.Staff);
foreach (var prop in typeof(ClaimPermission).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy))
{
await roleManager.AddClaimIfNotExists(staffRole, prop.GetValue(null).ToString());
}
我是 ASP.NET 的初学者,所以如果您有更好的解决方案,请告诉我.
I am a beginner in ASP.NET, so please let me know if you have better solutions.
而且,当我将所有声明/权限都放入 JWT 时,我不知道有多糟糕.太长?表现 ?我应该将生成的 JWT 存储在数据库中并稍后检查以获取有效用户的角色/声明吗?
And, I don't know how worst when I put all claims/permissions into JWT. Too long? Performance ? Should I store generated JWT in database and check it later for getting valid user's roles/claims?
这篇关于ASP.NET Core JWT 映射角色声明到 ClaimsIdentity的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!