由于您问到使用Base64进行解码,我将专注于该问题,而不是.NET中JWT的语义。这应该让JWT令牌神秘化一点。
注意,上面只有你的JWT字符串的第一部分是有效的,将其转换为{"alg":"HS256"}
,而第二个皈依aA1!
- 所以例如起见,我将使用http://jwt.io默认采样值:
var jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
所以,每JWT.io's introduction,你有一个JWT令牌只是三个部分:
假设令牌没有被加密,前两个段可以使用普通的Base64被解码(一旦垫的长度与四的倍数,如@Jacob如上所述)。最后一段只是一个加密签名;它不包含任何有意义的编码信息来解码。
所以,一个简单的代码片段,显示解码JWT内容看起来是这样的:
var decoded = jwt.Split('.')
.Take(2)
.Select(x =>
Encoding.UTF8.GetString(
Convert.FromBase64String(
x.PadRight(x.Length + (x.Length % 4), '='))))
.Aggregate((s1, s2) => s1 + Environment.NewLine + s2);
Console.WriteLine(decoded);
/* Prints:
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
*/
分开所有的lambda表达式可能看起来像一个简单的例子:
/// <summary>
/// A function to make the Base64 decoding a little less
/// verbose below:
/// </summary>
string Base64Decode(string value)
{
return Encoding.Default.GetString(Convert.FromBase64String(value));
}
// Get the first two segments into an enumerable:
var pieces = jwt.Split('.').Take(2);
// Pad them with equals signs to a length that is a multiple of four:
var paddedPieces = pieces.Select(x => x.PadRight(x.Length + (x.Length % 4), '='));
// Base64 decode the pieces:
var decodedPieces = paddedPieces.Select(x => Base64Decode(x));
// Join it all back into one string with .Aggregate:
Console.WriteLine(decodedPieces.Aggregate((s1, s2) => s1 + Environment.NewLine + s2));
结果这里与上面的一样。
当然,如果您打算进行有意义的JWT操作(如签名和验证),则应使用System.IdentityModel.Tokens.Jwt
中的JwtSecurityToken
类。但是,如果您只需要找出未加密的令牌包含哪些信息,就像上面那样简单。
您需要分别将填充添加到每个用点分隔的部分。 '='字符在JWT中无效,但在分析时,您必须添加它们。 – Jacob
我不确定你的意思,因为ReadToken需要一个字符串参数。你希望我分割(。)并添加= padding,然后将它们连接在一起? – mrusername
我认为这个错误是在你调用的方法中,而不是你发布的代码中。这是第三方库吗? – Jacob