我有一个 JWT 令牌从 API 返回到我的客户端应用程序,这是我的 JWT 代码:
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Sub, user.Email.ToString()),
new Claim(ApplicationConstants.UserId, applicationUser.Id.ToString()),
};
if (applicationUser.FirstName != null)
{
claims.Add(new Claim(ApplicationConstants.FirstName, applicationUser.FirstName));
}
if (applicationUser.NormalizedUserName != null)
{
claims.Add(new Claim(ApplicationConstants.UserName, applicationUser.NormalizedUserName));
}
//only if the user is vendor
if (vendorUser != null) {
claims.Add(new Claim(RoleNameConstants.Vendor, vendorUser.Id.ToString()));
claims.Add(new Claim(ApplicationConstants.VendorId, vendorUser.VendorId.ToString()));
}
var claimsIdentity = new ClaimsIdentity(claims);
//Adding UserClaims to JWT claims
foreach (var item in userRoles)
{
//claimsIdentity.AddClaim(new Claim(ApplicationConstants.Roles, item));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, item));
}
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret);
#region code smell - don't look
//var claims = new List<Claim>
//{
// new Claim(JwtRegisteredClaimNames.Sub, user.Email),
// new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
// new Claim(JwtRegisteredClaimNames.Email, user.Email),
// new Claim("id", user.Id)
//};
//var userClaims = await _userManager.GetClaimsAsync(user);
//claims.AddRange(userClaims);
//var userRoles = await _userManager.GetRolesAsync(user);
//foreach (var userRole in userRoles)
//{
// claims.Add(new Claim(ClaimTypes.Role, userRole));
// var role = await _roleManager.FindByNameAsync(userRole);
// if (role == null) continue;
// var roleClaims = await _roleManager.GetClaimsAsync(role);
// foreach (var roleClaim in roleClaims)
// {
// if (claims.Contains(roleClaim))
// continue;
// claims.Add(roleClaim);
// }
//}
#endregion
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claimsIdentity),
//Expires = DateTime.UtcNow.Add(_jwtSettings.TokenLifetime),
Expires = DateTime.UtcNow.AddDays(30),
SigningCredentials =
new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
我正在使用它在 ASP.NET Identity 中构建基于 cookie 的身份验证,如下所示:
var stream = response.Token;
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var token = handler.ReadToken(stream) as JwtSecurityToken;
//my code
var claims = new List<Claim>();
foreach (var tokenClaim in token.Claims)
{
var claim = new Claim(tokenClaim.Type, tokenClaim.Value);
claims.Add(claim);
}
var identity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme, ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
//var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme, nameType, roleType);
var principal = new ClaimsPrincipal(identity);
var authProperties = new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = userRequest == null ? false : userRequest.RememberMe,
ExpiresUtc = token.ValidTo,
IssuedUtc = DateTime.UtcNow
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
principal,
authProperties);
_httpContextAccessor.AddCookie("token", response.Token, token.ValidTo);
//_sessionManager.SetString("token", response.Token);
HttpContext.User = principal;
_httpContextAccessor.HttpContext.User = principal;
现在此代码可以正确地对用户进行身份验证,但是当我使用 [Authorize(Roles = "Vendor,VendorAdmin")]
属性时,这对于角色授权无法正常工作,即使用户拥有这些角色,它也不会让用户通过。>
这是我的启动代码:
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
x.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}/*CookieAuthenticationDefaults.AuthenticationScheme*/) // Sets the default scheme to cookies
.AddCookie(options =>
{
options.LoginPath = "/account/login";
options.AccessDeniedPath = "/home/error";
});
答案 0 :(得分:1)
我测试了你的场景。从 API 获取的声明中角色的键是字符串 role
。
但是 Roles
中的 [Authorize(Roles = "Vendor,VendorAdmin")]
需要密钥 http://schemas.microsoft.com/ws/2008/06/identity/claims/role
。
然后在基于 cookie 的身份验证项目中重新添加角色。
foreach (var tokenClaim in token.Claims)
{
if (tokenClaim.Type == "role")
{
claims.Add(new Claim(ClaimTypes.Role, tokenClaim.Value));
continue;
}
var claim = new Claim(tokenClaim.Type, tokenClaim.Value);
claims.Add(claim);
}
然后就可以访问授权的方法了。
[Authorize(Roles = "Vendor")]
public IActionResult Resource()
{
return Ok();
}