ASP.NET声明NameIdentifier Id获取转换错误

时间:2018-05-29 15:43:26

标签: c# asp.net asp.net-identity claims-based-identity

我对此代码有疑问:

    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错误消失...无法找到有关它的任何信息。

5 个答案:

答案 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())
    };