JWT 无法将头部解码为 Base64Url 编码的字符串。

8
我有以下代码:
public async Task<LoginResult> GenerateJwtTokenAsync(string email, string password)
{
    LoginResult loginResult = await _membershipProvider.Login(email, password);
    if (loginResult.Succeeded)
    {
        var symmetricKey = Convert.FromBase64String(Secret);

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(loginResult.Claims),
            Expires = DateTime.UtcNow.AddDays(1),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256Signature)
        };

        var stoken = _tokenHandler.CreateToken(tokenDescriptor);
        var token = _tokenHandler.WriteToken(stoken);

        // Check token here to see if it works
        var jwtToken = _tokenHandler.ReadToken(token) as JwtSecurityToken;
        loginResult.JwtToken = token;
    }
    return loginResult;
}

public ClaimsPrincipal ValidateJwtToken(string tokenString)
{

    ClaimsPrincipal principal;

    try
    {
        var jwtToken = _tokenHandler.ReadToken(tokenString) as JwtSecurityToken;

        if (jwtToken == null)
        {
            principal = null;
        }
        else
        {
            var symmetricKey = Convert.FromBase64String(Secret);

            var validationParameters = new TokenValidationParameters()
            {
                RequireExpirationTime = true,
                ValidateIssuer = false,
                ValidateAudience = false,
                IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
            };

            SecurityToken securityToken;
            principal = _tokenHandler.ValidateToken(tokenString, validationParameters, out securityToken);
        }
    }
    catch (Exception ex)
    {
        principal = null;
    }

    return principal;
}

下面这行代码可以正常读取令牌,但是在第二个方法中读取时会抛出异常。
// Check token here to see if it works
var jwtToken = _tokenHandler.ReadToken(token) as JwtSecurityToken

我已经验证了这两个字符串是相同的,但当我想要验证令牌时,它却停止工作,我非常困惑,不知道我做错了什么。请问有什么想法吗?
编辑:
异常
   "IDX10729: Unable to decode the header 'header' as Base64Url encoded string. jwtEncodedString: 'Token here'."

堆栈跟踪:

   at System.IdentityModel.Tokens.Jwt.JwtSecurityToken.Decode(String[] tokenParts, String rawData)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ReadJwtToken(String token)
   at AuthService.ValidateJwtToken(String tokenString) in AuthService.cs:line 57

我遇到了一个异常 - 那是什么异常?始终提供您收到的任何错误的详细信息... - Jon Skeet
@JonSkeet 抱歉我打字太快了,部分原因是因为这是一个很大的异常,现在我会更新的 :D - LukeHennerley
你仅仅展示了InnerException,而且似乎只是其中的一部分。一个包含所有内部异常的完整堆栈跟踪将更容易理解。(考虑到这是一个类型初始化器失败,这似乎使用了不同的代码...) - Jon Skeet
jwtEncodedString: 'Token here' 似乎不太适合。这是您自己更改的有效令牌,还是无效的?即使您认为它们相同,也可能存在两个不同的字符串。我建议加入更多日志记录。 - Jon Skeet
没错,听起来需要更多的日志记录。 - Jon Skeet
显示剩余4条评论
5个回答

15

我遇到一个错误,并通过观察错误细节发现,原因是 Newtonsoft.Json dll 未加载。

System.IdentityModel.Tokens.Jwt.JsonExtensions 尝试加载dll的9.0.0.0版本,但项目正在使用10.0.0.0版本。 错误详细信息类似于以下内容:

  

System.ArgumentException:IDX10729:...无法加载文件或程序集“Newtonsoft.Json,Version=9.0.0.0,Culture=neutral,PublicKeyToken=30ad4fe6b2a6aeed”或其某个依赖项

我通过将以下绑定添加到配置中解决了此问题:

 <runtime>
    <assemblyBinding  xmlns="urn:schemas-microsoft-com:asm.v1">
       <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

请注意,如果解决方案在不同的项目中引用此组件,则可能会为此目的创建多个配置。 - DanielV

2
尝试将库更新到最新版本。在我的情况下, System.IdentityModel.Tokens.Jwt,Version=6.5.0.0 解决了这个问题。

1

我也遇到了相同的错误,在验证令牌时。我通过将Newtonsoft.Json dll添加到项目中解决了此问题。


在 NUnit 项目中遇到了同样的问题,而主要项目却运行良好。发现这些项目使用了不同版本的 Newtonsoft.Json,在为 NUnit 刷新版本后问题消失了。 - Grigorii

0
JWT库(例如ValidateToken)要求输入的令牌字符串长度必须是4的倍数。您可能需要“右填充”输入以使其可被4整除;填充字符是等号。 对于您的第二种方法,您可以使用以下代码片段确保'tokenString'已正确右填充"=":
 tokenString= tokenString.PadRight(tokenString.Length + (4 - tokenString.Length % 4) % 4, '=');

0
在我的情况下,当这个包[System.IdentityModel.Tokens.Jwt]丢失时,我遇到了一个类似的异常:
"IDX12729: Unable to decode the header '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]' as Base64Url encoded string. jwtEncodedString: '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'."

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接