.net 使用 System.IdentityModel.Tokens.Jwt 解码和验证 JWT 令牌

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18677837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:26:46  来源:igfitidea点击:

Decoding and verifying JWT token using System.IdentityModel.Tokens.Jwt

.netwifjwt

提问by w.brian

I've been using the JWTlibrary to decode a Json Web Token, and would like to switch to Microsoft's official JWT implementation, System.IdentityModel.Tokens.Jwt.

我一直在使用JWT库来解码 Json Web Token,并且想切换到 Microsoft 的官方 JWT 实现System.IdentityModel.Tokens.Jwt

The documentation is very sparse, so I'm having a hard time figuring how to accomplish what I've been doing with the JWT library. With the JWT library, there is a Decode method that takes the base64 encoded JWT and turns it into JSON which can then be deserialized. I'd like to do something similar using System.IdentityModel.Tokens.Jwt, but after a fair amount of digging, cannot figure out how.

文档非常稀少,所以我很难弄清楚如何使用 JWT 库完成我一直在做的事情。在 JWT 库中,有一个 Decode 方法可以将 base64 编码的 JWT 转换为 JSON,然后可以反序列化。我想使用 System.IdentityModel.Tokens.Jwt 做类似的事情,但经过大量挖掘后,无法弄清楚如何。

For what it's worth, I'm reading the JWT token from a cookie, for use with Google's identity framework.

就其价值而言,我正在从 cookie 中读取 JWT 令牌,以便与 Google 的身份框架一起使用。

Any help would be appreciated.

任何帮助,将不胜感激。

回答by Mike Goodwin

Within the package there is a class called JwtSecurityTokenHandlerwhich derives from System.IdentityModel.Tokens.SecurityTokenHandler. In WIF this is the core class for deserialising and serialising security tokens.

在包中有一个类JwtSecurityTokenHandler,它派生自System.IdentityModel.Tokens.SecurityTokenHandler. 在 WIF 中,这是用于反序列化和序列化安全令牌的核心类。

The class has a ReadToken(String)method that will take your base64 encoded JWT string and returns a SecurityTokenwhich represents the JWT.

该类有一个ReadToken(String)方法,该方法将采用 base64 编码的 JWT 字符串并返回SecurityToken代表 JWT 的 a。

The SecurityTokenHandleralso has a ValidateToken(SecurityToken)method which takes your SecurityTokenand creates a ReadOnlyCollection<ClaimsIdentity>. Usually for JWT, this will contain a single ClaimsIdentityobject that has a set of claims representing the properties of the original JWT.

SecurityTokenHandler也有ValidateToken(SecurityToken)这需要你的方法SecurityToken,并创建一个ReadOnlyCollection<ClaimsIdentity>。通常对于 JWT,这将包含一个ClaimsIdentity对象,该对象具有一组表示原始 JWT 属性的声明。

JwtSecurityTokenHandlerdefines some additional overloads for ValidateToken, in particular, it has a ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)overload. The TokenValidationParametersargument allows you to specify the token signing certificate (as a list of X509SecurityTokens). It also has an overload that takes the JWT as a stringrather than a SecurityToken.

JwtSecurityTokenHandler为 定义了一些额外的重载ValidateToken,特别是它有一个ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)重载。该TokenValidationParameters参数允许您指定令牌签名证书(作为 的列表X509SecurityTokens)。它还有一个重载,将 JWT 作为 astring而不是SecurityToken.

The code to do this is rather complicated, but can be found in the Global.asax.cx code (TokenValidationHandlerclass) in the developer sample called "ADAL - Native App to REST service - Authentication with ACS via Browser Dialog", located at

执行此操作的代码相当复杂,但可以在TokenValidationHandler名为“ADAL - Native App to REST service - Authentication with ACS via Browser Dialog”的开发人员示例中的 Global.asax.cx 代码(类)中找到,位于

http://code.msdn.microsoft.com/AAL-Native-App-to-REST-de57f2cc

http://code.msdn.microsoft.com/AAL-Native-App-to-REST-de57f2cc

Alternatively, the JwtSecurityTokenclass has additional methods that are not on the base SecurityTokenclass, such as a Claimsproperty that gets the contained claims without going via the ClaimsIdentitycollection. It also has a Payloadproperty that returns a JwtPayloadobject that lets you get at the raw JSON of the token. It depends on your scenario which approach it most appropriate.

或者,JwtSecurityToken该类具有不在基SecurityToken类上的其他方法,例如Claims无需通过ClaimsIdentity集合即可获取包含的声明的属性。它还具有Payload返回一个JwtPayload对象的属性,该对象可让您获取令牌的原始 JSON。这取决于您的场景,哪种方法最合适。

The general (i.e. non JWT specific) documentation for the SecurityTokenHandlerclass is at

SecurityTokenHandler该类的一般(即非 JWT 特定)文档位于

http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.securitytokenhandler.aspx

http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.securitytokenhandler.aspx

Depending on your application, you can configure the JWT handler into the WIF pipeline exactly like any other handler.

根据您的应用程序,您可以像任何其他处理程序一样将 JWT 处理程序配置到 WIF 管道中。

There are 3 samples of it in use in different types of application at

有 3 个样本在不同类型的应用中使用

http://code.msdn.microsoft.com/site/search?f%5B0%5D.Type=SearchText&f%5B0%5D.Value=aal&f%5B1%5D.Type=User&f%5B1%5D.Value=Azure%20AD%20Developer%20Experience%20Team&f%5B1%5D.Text=Azure%20AD%20Developer%20Experience%20Team

http://code.msdn.microsoft.com/site/search?f%5B0%5D.Type=SearchText&f%5B0%5D.Value=aal&f%5B1%5D.Type=User&f%5B1%5D.Value=Azure% 20AD%20Developer%20Experience%20Team&f%5B1%5D.Text=Azure%20AD%20Developer%20Experience%20Team

Probably, one will suite your needs or at least be adaptable to them.

可能,一个会满足您的需求,或者至少可以适应它们。

回答by Regfor

I am just wondering why to use some libraries for JWT token decoding and verification at all.

我只是想知道为什么要使用一些库来进行 JWT 令牌解码和验证。

Encoded JWT token can be created using following pseudocode

可以使用以下伪代码创建编码的 JWT 令牌

var headers = base64URLencode(myHeaders);
var claims = base64URLencode(myClaims);
var payload = header + "." + claims;

var signature = base64URLencode(HMACSHA256(payload, secret));

var encodedJWT = payload + "." + signature;

It is very easy to do without any specific library. Using following code:

无需任何特定库即可轻松完成。使用以下代码:

using System;
using System.Text;
using System.Security.Cryptography;

public class Program
{   
    // More info: https://stormpath.com/blog/jwt-the-right-way/
    public static void Main()
    {           
        var header = "{\"typ\":\"JWT\",\"alg\":\"HS256\"}";
        var claims = "{\"sub\":\"1047986\",\"email\":\"[email protected]\",\"given_name\":\"John\",\"family_name\":\"Doe\",\"primarysid\":\"b521a2af99bfdc65e04010ac1d046ff5\",\"iss\":\"http://example.com\",\"aud\":\"myapp\",\"exp\":1460555281,\"nbf\":1457963281}";

        var b64header = Convert.ToBase64String(Encoding.UTF8.GetBytes(header))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");
        var b64claims = Convert.ToBase64String(Encoding.UTF8.GetBytes(claims))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");

        var payload = b64header + "." + b64claims;
        Console.WriteLine("JWT without sig:    " + payload);

        byte[] key = Convert.FromBase64String("mPorwQB8kMDNQeeYO35KOrMMFn6rFVmbIohBphJPnp4=");
        byte[] message = Encoding.UTF8.GetBytes(payload);

        string sig = Convert.ToBase64String(HashHMAC(key, message))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");

        Console.WriteLine("JWT with signature: " + payload + "." + sig);        
    }

    private static byte[] HashHMAC(byte[] key, byte[] message)
    {
        var hash = new HMACSHA256(key);
        return hash.ComputeHash(message);
    }
}

The token decoding is reversed version of the code above.To verify the signature you will need to the same and compare signature part with calculated signature.

令牌解码是上面代码的反向版本。要验证签名,您需要将签名部分与计算出的签名相同并进行比较。

UPDATE: For those how are struggling how to do base64 urlsafe encoding/decoding please see another SO question, and also wiki and RFCs

更新:对于那些正在努力如何进行 base64 url​​safe 编码/解码的人,请参阅另一个SO 问题,以及 wiki 和 RFC