我对此代码有疑问:
private async Task<object> GenerateJwtToken(string email, User user)
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
用户扩展IdentityUser。问题是我得到“无法从'int'转换为'System.Security.Claims.ClaimsIdentity'”。 即使对于ClaimTypes.NameIdentifier,我也会收到错误:“无法从'string'转换为'System.IO.BinaryReader'”。如果我将Id更改为其他内容,例如电子邮件,或者firstName错误消失...无法找到有关它的任何信息。
答案 0 :(得分:4)
我在新Claim(ClaimTypes.Name, userFromRepo.Username)
的Visual Code上遇到此错误,告诉Argument 1: cannot convert from 'string' to 'System.IO.BinaryReader'
。我的代码是这样的:
public async Task<IActionResult> ReadUser([FromBody]UserDto userDto){
User userFromRepo = _authRepository.GetUserAsync();
//generate token for user
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("my secret key");
var tokenDescriptor = new SecurityTokenDescriptor{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()),
new Claim(ClaimTypes.Name, userFromRepo.Username) //error here in this ctor
}),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
};
在我的存储库方法之前添加了await
关键字之后,该方法是异步的,现在错误消失了。
public async Task<IActionResult> ReadUser([FromBody]UserDto userDto){
User userFromRepo = await _authRepository.GetUserAsync(); //added await
//generate token for user
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("my secret key");
var tokenDescriptor = new SecurityTokenDescriptor{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()),
new Claim(ClaimTypes.Name, userFromRepo.Username) //error gets fixed
}),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
};
也许您正面临与此类似的事情?
答案 1 :(得分:2)
我对这个问题有点迟了,但是我遇到了类似的问题。
我发现新的Claim具有多个可以传递给它的签名。明确说明类型可以解决我的问题。
new Claim(ClaimTypes.Name as string, userFromRepo.Username as string)
希望这会对其他遇到此问题的人有所帮助。
答案 2 :(得分:1)
通常(至少在ASP.NET Core 3中)它是如何工作的,是当脚手架实例化sub
JWT声明时(由InboundClaimTypeMap
自动转换为NameIdentifier
)。 ClaimsPrincipal
。
因此只需设置一个JwtRegisteredClaimNames.Sub
声明,并将user.Id作为值即可。
但是您可以通过在IdentityOptions.ClaimsIdentity.UserIdClaimType
调用中为AddIdentity()
分配一个值来定制标识应用于身份识别的主张,例如:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.ClaimsIdentity.UserIdClaimType = JwtRegisteredClaimNames.Sub;
});
如果要禁用声明映射,可以通过在配置中包含以下语句来清除映射:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
或将此标志设置为false:
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
答案 3 :(得分:0)
在我的情况下,我的方法签名出现了构建错误。修复后,错误已修复
我的方法签名如下:
private async Task<User> AuthenticateUserAsync(string email, string password)
在定义“用户”类后,与方法签名相关的构建错误已修复。
答案 4 :(得分:0)
将 user.Id
转换为字符串
private async Task<object> GenerateJwtToken(string email, User user)
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
};