JWT Base64解码遇System.FormatException问题求助
JWT解码触发
System.FormatException问题 错误详情
System.FormatException: 'The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.'
解码代码
// token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTExODcyODcsImlzcyI6IlRlc3QuY29tIiwiYXVkIjoiVGVzdC5jb20ifQ.pgzHJVC-iuvPaMuYzFNwPREFQsUVsLlKia11AM3ai1Y string[] tokens = token.Split('.'); // first tokenPart = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 解码正常 // second tokenPart = eyJleHAiOjE3MTExODcyODcsImlzcyI6IlRlc3QuY29tIiwiYXVkIjoiVGVzdC5jb20ifQ 解码失败 foreach (string tokenPart in tokens) { string decodedString = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(tokenPart)); }
出错的Token片段
eyJleHAiOjE3MTExODQ3MDUsImlzcyI6IlRlc3QuY29tIiwiYXVkIjoiVGVzdC5jb20ifQ
该片段可正常解码为:
{"exp":1711179891,"iss":"Test.com","aud":"Test.com"}
JWT由以下服务端代码生成:
public string GenerateJSONWebToken(int userID, string key, string issuer) { SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); SigningCredentials credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); JwtSecurityToken token = new JwtSecurityToken( issuer, issuer, null, expires: DateTime.Now.AddSeconds(10), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); }
解决方案
问题核心:JWT的Header和Payload采用Base64Url编码,而非标准Base64编码,两者差异如下:
- Base64Url将
+替换为-、/替换为_ - Base64Url会省略末尾的填充字符
=
直接用Convert.FromBase64String解码会因格式不匹配报错,需先将Base64Url转换为标准Base64格式。
手动修正编码的解码代码
string[] tokens = token.Split('.'); foreach (string tokenPart in tokens) { if (string.IsNullOrEmpty(tokenPart)) continue; // 转换Base64Url到标准Base64 string base64 = tokenPart .Replace('-', '+') .Replace('_', '/'); // 补全填充字符 switch (base64.Length % 4) { case 2: base64 += "=="; break; case 3: base64 += "="; break; } string decodedString = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(base64)); }
更可靠的方式:用JWT库直接解析
既然生成JWT用的是System.IdentityModel.Tokens.Jwt库,直接用同库解析更省心,无需手动处理编码:
var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = handler.ReadJwtToken(token); // 直接获取Header和Payload var headerData = jwtToken.Header; var payloadData = jwtToken.Payload; // 示例:序列化Payload输出 Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(payloadData));
这种方式还支持后续的签名验证(若需要),避免手动处理编码的潜在问题。
内容的提问来源于stack exchange,提问作者GuidoG
相关产品推荐
相关产品推荐

