2017-03-28 99 views
1

我有一个JWT令牌“eyJhbGciOiJIUzI1NiJ9.YUExIQ.srnc87a8Se8arhCopLBpgxEvILA2AZxOB8BIrFDHKL4 ” 那是在节点编码和我想在C#进行解码,但我发现一个错误抛出它对负载感到不安。解码JWT错误:无法解码有效负载为Base64Url编码字符串

public void Consume(BasicDeliverEventArgs msg) 
    { 
     var message = Encoding.UTF8.GetString(msg.Body); 
     var user = JsonConvert.DeserializeObject<User>(message); 

     var handler = new JwtSecurityTokenHandler(); 

     try 
     {  
      var x = handler.ReadToken(user.Password) as JwtSecurityToken; 
     } 
     catch(Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 



     _repo.UpdateUser(user); 
    } 

返回错误:无法有效载荷“YUExIQ”作为Base64Url编码字符串解码

我不知道那里有什么地方我可以把在于使用了解码编码的地方,或者如果秘密我不知何故需要转换有效载荷base64或如果我只是失去了某些步骤的地方。提前致谢。

回答

0

使用JWT,您可以省略填充字节。 .NET需要在末尾填充=字符,以使字符的数量为4的倍数。YUExIQ==应该可解码。

+0

您需要分别将填充添加到每个用点分隔的部分。 '='字符在JWT中无效,但在分析时,您必须添加它们。 – Jacob

+0

我不确定你的意思,因为ReadToken需要一个字符串参数。你希望我分割(。)并添加= padding,然后将它们连接在一起? – mrusername

+0

我认为这个错误是在你调用的方法中,而不是你发布的代码中。这是第三方库吗? – Jacob

0

由于您问到使用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类。但是,如果您只需要找出未加密的令牌包含哪些信息,就像上面那样简单。