JWT解码时字符串声明类型错误?
String Claim Types Error when JWT Decoding?
当我执行登录操作时,JWT 令牌作为响应返回。但是,当我用 JS 解码时,我得到这个:
{http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: '1', http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: 'RESMAK ', http://schemas.microsoft.com/ws/2008/06/identity/claims/role: 'Administrator', FirmNumber: '1', PeriodNumber: '1', …}
FirmNumber: "1"
PeriodNumber: "1"
aud: "Audience"
exp: 1639301639
http://schemas.microsoft.com/ws/2008/06/identity/claims/role: "Administrator"
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: "RESMAK "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: "1"
iss: "Issuer"
nbf: 1639215239
[[Prototype]]: Object
我想成为
FirmNumber: "1"
PeriodNumber: "1"
aud: "Audience"
exp: 1639301639
role: "Administrator"
name: "RESMAK "
nameidentifier: "1"
iss: "Issuer"
可能是什么原因?
.Net Core 3.1 与 TypeScript 反应
我通过 JwtHelper 创建令牌 Class
public class JwtHelper
{
public IConfiguration Configuration { get; }
private TokenOptions _tokenOptions;
private DateTime _accessTokenExpiration;
public JwtHelper(IConfiguration configuration)
{
Configuration = configuration;
_tokenOptions = Configuration.GetSection("TokenOptions").Get<TokenOptions>();
}
public AccessToken CreateToken(User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto)
{
_accessTokenExpiration = DateTime.Now.AddMinutes(_tokenOptions.AccessTokenExpiration);
var securityKey = SecurityKeyHelper.CreateSecurityKey(_tokenOptions.SecurityKey);
var signingCredentials = SigningCredentialsHelper.CreateSigningCredentials(securityKey);
var jwt = CreateJwtSecurityToken(_tokenOptions, user, operationClaims, userForLoginDto, signingCredentials);
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var token = jwtSecurityTokenHandler.WriteToken(jwt);
return new AccessToken
{
Token = token,
Expration = _accessTokenExpiration
};
}
//securityKey ,signingCredentials ve diger token optionsdan gelen bilgileri toplayarak bir JwtToken Üretiyoruz.
public JwtSecurityToken CreateJwtSecurityToken(TokenOptions tokenOptions, User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto, SigningCredentials signingCredentials)
{
var jwt = new JwtSecurityToken
(
issuer: tokenOptions.Issuer,
audience: tokenOptions.Audience,
expires: _accessTokenExpiration,
notBefore: DateTime.Now,
claims: SetClaims(user, operationClaims, userForLoginDto),
signingCredentials: signingCredentials
);
return jwt;
}
private IEnumerable<Claim> SetClaims(User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto)
{
var claims = new List<Claim>();
claims.AddNameIdentifier(user.Id.ToString());
claims.AddName($"{user.FirstName} {user.LastName}");
claims.AddRoles(operationClaims.Select(x => x.Name).ToArray());
claims.AddFirmNumber(userForLoginDto.FirmNumber.ToString());
claims.AddPeriodNumber(userForLoginDto.PeriodNumber.ToString());
return claims;
}
}
public static class ClaimExtensions
{
public const string ClaimTypeFirmNumber = "FirmNumber";
public const string ClaimTypePeriodNumber = "PeriodNumber";
public static void AddName(this ICollection<Claim> claims, string name)
{
claims.Add(new Claim(ClaimTypes.Name, name));
}
public static void AddNameIdentifier(this ICollection<Claim> claims, string nameIdentifier)
{
claims.Add(new Claim(ClaimTypes.NameIdentifier, nameIdentifier));
}
public static void AddRoles(this ICollection<Claim> claims, string[] roles)
{
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
}
public static void AddPeriodNumber(this ICollection<Claim> claims, string periodNumber)
{
claims.Add(new Claim(ClaimTypePeriodNumber, periodNumber));
}
public static void AddFirmNumber(this ICollection<Claim> claims, string firmNumber)
{
claims.Add(new Claim(ClaimTypeFirmNumber, firmNumber));
}
}
我使用 SigningCredentials 作为 SecurityAlgorithms.HmacSha256Signature
public class SigningCredentialsHelper
{
public static SigningCredentials CreateSigningCredentials(SecurityKey securityKey)
{
return new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);//GEnellikle bu şifreleme algoritması kullanılır
}
}
最后我用 JwtDecode 库解码了令牌
const decodedToken = jwtDecode(response.data.token)
问题是 OpenIDConnect/OAuth 和 Microsoft 对于声明名称应该是什么有不同的意见,默认情况下 .NET 会在幕后重命名一些声明。
要停止此操作,您需要使用以下方法关闭声明映射:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
然后你需要告诉 .NET name/role 声明的名称应该是什么,通过设置:
opt.TokenValidationParameters.RoleClaimType = "roles";
opt.TokenValidationParameters.NameClaimType = "name";
有关声明映射的更多详细信息,请访问:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/claims?view=aspnetcore-6.0
当我执行登录操作时,JWT 令牌作为响应返回。但是,当我用 JS 解码时,我得到这个:
{http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: '1', http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: 'RESMAK ', http://schemas.microsoft.com/ws/2008/06/identity/claims/role: 'Administrator', FirmNumber: '1', PeriodNumber: '1', …}
FirmNumber: "1"
PeriodNumber: "1"
aud: "Audience"
exp: 1639301639
http://schemas.microsoft.com/ws/2008/06/identity/claims/role: "Administrator"
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: "RESMAK "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: "1"
iss: "Issuer"
nbf: 1639215239
[[Prototype]]: Object
我想成为
FirmNumber: "1"
PeriodNumber: "1"
aud: "Audience"
exp: 1639301639
role: "Administrator"
name: "RESMAK "
nameidentifier: "1"
iss: "Issuer"
可能是什么原因? .Net Core 3.1 与 TypeScript 反应
我通过 JwtHelper 创建令牌 Class
public class JwtHelper
{
public IConfiguration Configuration { get; }
private TokenOptions _tokenOptions;
private DateTime _accessTokenExpiration;
public JwtHelper(IConfiguration configuration)
{
Configuration = configuration;
_tokenOptions = Configuration.GetSection("TokenOptions").Get<TokenOptions>();
}
public AccessToken CreateToken(User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto)
{
_accessTokenExpiration = DateTime.Now.AddMinutes(_tokenOptions.AccessTokenExpiration);
var securityKey = SecurityKeyHelper.CreateSecurityKey(_tokenOptions.SecurityKey);
var signingCredentials = SigningCredentialsHelper.CreateSigningCredentials(securityKey);
var jwt = CreateJwtSecurityToken(_tokenOptions, user, operationClaims, userForLoginDto, signingCredentials);
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var token = jwtSecurityTokenHandler.WriteToken(jwt);
return new AccessToken
{
Token = token,
Expration = _accessTokenExpiration
};
}
//securityKey ,signingCredentials ve diger token optionsdan gelen bilgileri toplayarak bir JwtToken Üretiyoruz.
public JwtSecurityToken CreateJwtSecurityToken(TokenOptions tokenOptions, User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto, SigningCredentials signingCredentials)
{
var jwt = new JwtSecurityToken
(
issuer: tokenOptions.Issuer,
audience: tokenOptions.Audience,
expires: _accessTokenExpiration,
notBefore: DateTime.Now,
claims: SetClaims(user, operationClaims, userForLoginDto),
signingCredentials: signingCredentials
);
return jwt;
}
private IEnumerable<Claim> SetClaims(User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto)
{
var claims = new List<Claim>();
claims.AddNameIdentifier(user.Id.ToString());
claims.AddName($"{user.FirstName} {user.LastName}");
claims.AddRoles(operationClaims.Select(x => x.Name).ToArray());
claims.AddFirmNumber(userForLoginDto.FirmNumber.ToString());
claims.AddPeriodNumber(userForLoginDto.PeriodNumber.ToString());
return claims;
}
}
public static class ClaimExtensions
{
public const string ClaimTypeFirmNumber = "FirmNumber";
public const string ClaimTypePeriodNumber = "PeriodNumber";
public static void AddName(this ICollection<Claim> claims, string name)
{
claims.Add(new Claim(ClaimTypes.Name, name));
}
public static void AddNameIdentifier(this ICollection<Claim> claims, string nameIdentifier)
{
claims.Add(new Claim(ClaimTypes.NameIdentifier, nameIdentifier));
}
public static void AddRoles(this ICollection<Claim> claims, string[] roles)
{
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
}
public static void AddPeriodNumber(this ICollection<Claim> claims, string periodNumber)
{
claims.Add(new Claim(ClaimTypePeriodNumber, periodNumber));
}
public static void AddFirmNumber(this ICollection<Claim> claims, string firmNumber)
{
claims.Add(new Claim(ClaimTypeFirmNumber, firmNumber));
}
}
我使用 SigningCredentials 作为 SecurityAlgorithms.HmacSha256Signature
public class SigningCredentialsHelper
{
public static SigningCredentials CreateSigningCredentials(SecurityKey securityKey)
{
return new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);//GEnellikle bu şifreleme algoritması kullanılır
}
}
最后我用 JwtDecode 库解码了令牌 const decodedToken = jwtDecode(response.data.token)
问题是 OpenIDConnect/OAuth 和 Microsoft 对于声明名称应该是什么有不同的意见,默认情况下 .NET 会在幕后重命名一些声明。
要停止此操作,您需要使用以下方法关闭声明映射:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
然后你需要告诉 .NET name/role 声明的名称应该是什么,通过设置:
opt.TokenValidationParameters.RoleClaimType = "roles";
opt.TokenValidationParameters.NameClaimType = "name";
有关声明映射的更多详细信息,请访问:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/claims?view=aspnetcore-6.0