IdentityServer4之JWT签名(RSA加密证书)及验签

1、前言


 在IdentityServer4中有两种令牌,一个是JWT和Reference Token,在IDS4中默认用的是JWT,那么这二者有什么区别呢?node

 

2、JWT与Reference Token的区别


 一、JWT(不可撤回)  算法

  JWT是一个很是轻巧的规范,通常被用来在身份提供者和服务提供者间传递安全可靠的信息。JWT令牌是一个自包含的访问令牌 - 它是一个带有声明和过时的受保护数据结构。一旦API了解了密钥材料,它就能够验证自包含的令牌,而无需与发行者进行通讯。这使得JWT难以撤销。它们将一直有效,直到它们过时。json

  JWT常被用于先后端分离,能够和 Restful API 配合使用,经常使用于构建身份认证机制,一个 JWT 实际上就是一个字符串,它包含了使用.分隔的三部分: Header 头部 Payload 负载 Signature 签名(格式:Header.Payload.Signature)后端

在这个三个部分中最关键的就是signature。api

  signature:被用来确认JWT信息的发送者是谁,并保证信息没有被篡改,使用header中指定的算法将编码后的header、编码后的payload、一个secret进行加密。所以签名算法推荐使用RSA或ECDSA非对称加密算法。缓存

JWT特色:安全

  A、JWT 默认是不加密,但也是能够加密的。生成原始 Token 之后,能够用密钥再加密一次。服务器

  B、为了减小盗用,JWT 不该该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输微信

  C、jwt去中心化的思想:api资源收到第一个请求以后,会去id4服务器获取公钥,而后用公钥验证token是否合法,若是合法进行后面的有效性验证。有且只有第一个请求才会去id4服务器请求公钥,后面的请求都会用第一次请求的公钥来验证,这也是jwt去中心化验证的思想。(注:若是签名证书发生改变则须要重启有请求ids4服务器的资源服务器。)markdown

  D、JWT 自己包含了认证信息,一旦泄露,任何人均可以得到该令牌的全部权限。为了减小盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

 

二、Reference Token(不携带任何用户数据,可撤回)

  当使用 Reference token 的时候,服务端会对 Token 进行持久化,当客户端请求资源端(API)的时候,资源端须要每次都去服务端通讯去验证 Token 的合法性[/connect/introspect],IdentityServer4.AccessTokenValidation 中间件中能够配置缓存必定的时候去验证,而且 Token 是支持撤销[/connect/revocation]的。

  使用引用令牌时 - IdentityServer会将令牌的内容存储在数据存储中,而且只会将此令牌的惟一标识符发回给客户端。接收此引用的API必须打开与IdentityServer的反向通道通讯以验证令牌。以下:access_token就是惟一标识。(注不携带任何数据)

 

   当 AccessTokenType 定义为 Reference 的时候,验证资源端要注意配置 ApiSecrets 以确保 POST /connect/introspect HTTP/1.1 接口能验证经过,当 AccessTokenType 定义为 Jwt 的时候则资源端可不配置 options.ApiSecret 选项。以下图:

 

Reference Token官方图以下:

 以上就是JWT与Reference token的区别。为了减小访问中心服务器的资源,使用JWT仍是很是棒的,毕竟与服务器交互的资源仍是很是的昂贵的。不过具体的还得视实际状况而定。

那么咱们来看一下在IDS4中API使用JWT以及Reference Token的交互流程图

 

3、IDS4中API使用JWT以及Reference Token与认证中心的交互流程图


此图为:JWT,固然你们能够经过fiddler 抓包工具来查看一下具体的数据流就能明白其中的道理。

注:资源服务器在第一次解析AccessToken的时候会先到受权服务器获取配置数据(例如会访问:http://localhost:5000/.well-known/openid-configuration 获取配置的,http://localhost:5000/.well-known/openid-configuration/jwks 获取jwks)),以后解析AccessToken都会使用第一次获取到的配置数据,所以若是受权服务的配置更改了(加密证书等等修改了),那么应该重启资源服务器使之从新获取新的配置数据;

 

 此图为:Reference Token

 以上即JWT与Reference Token 流程图。

4、JWT中使用RSA加密


在说明JWT使用RSA加密以前咱们先来比较一下其余的加密算法

一、HS256与RS256的区别

  HS256 使用密钥生成固定的签名,RS256 使用成非对称进行签名。简单地说,HS256 必须与任何想要验证 JWT的 客户端或 API 共享秘密。即 以下图

 

  RS256 生成非对称签名,这意味着必须使用私钥来签签名 JWT,而且必须使用对应的公钥来验证签名。与对称算法不一样,使用 RS256 能够保证服务端是 JWT 的签名者,由于服务端是惟一拥有私钥的一方。这样作将再也不须要在许多应用程序之间共享私钥


二、建立自签名证书(操做步骤)

  生产环境(负载集群)通常须要使用固定的证书签名与验签,以确保重启服务端或负载的时候 Token 都能验签经过。(不使用临时证书)

那么证书如何生成请看下面分解步骤:

  第一种:使用OpenSSL生成证书,注:RSA加密证书长度要2048以上,不然服务运行会抛异常

#Linux系统生成证书:(推荐使用) sudo yum install openssl (CentOS)
#生成私钥文件 openssl genrsa
-out idsrv4.key 2048

#建立证书签名请求文件 CSR(Certificate Signing Request),用于提交给证书颁发机构(即 Certification Authority (CA))即对证书签名,申请一个数字证书。 openssl req -new -key idsrv4.key -out idsrv4.csr
#生成自签名证书(证书颁发机构(CA)签名后的证书,由于本身作测试那么证书的申请机构和颁发机构都是本身,crt 证书包含持有人的信息,持有人的公钥,以及签署者的签名等信息。当用户安装了证书以后,便意味着信任了这份证书,同时拥有了其中的公钥。) openssl x509
-req -days 365 -in idsrv4.csr -signkey idsrv4.key -out idsrv4.crt (包含公钥)
#自签名证书与私匙合并成一个文件(注:.pfx中能够加密码保护,因此相对安全些) openssl pkcs12
-export -in idsrv4.crt -inkey idsrv4.key -out idsrv4.pfx (注:在生成的过程当中会让咱们输入Export Password)

 

 证书截图以下:

 

  第二种:

openssl req -newkey rsa:2048 -nodes -keyout idsrv4.key -x509 -days 365 -out idsrv4.cer openssl pkcs12 -export -in idsrv4.cer -inkey idsrv4.key -out idsrv4.pfx

 

生成以下:

 

三、证书生成以后就可进入VS2017中配置

拷贝生成的证书,放到认证/受权服务器项目中。(VS中配置文件设置文件始终复制),最后把证书路径和密码配置到 IdentityServer 中,由于咱们自签名的证书是 PKCS12 (我的数字证书标准,Public Key Cryptography Standards #12) 标准包含私钥与公钥)标准,包含了公钥和私钥。

 A、在appsetting.json 配置文件中添加以下:此处须要配置password,自定义便可。

 

B、在starup.cs中ConfigureServices方法中配置以下便可。

 

配置完后便可。咱们启动IDS4项目便可生成加密的token。

 

将获得的token在jwt.io 网站来认证一下:把后缀为 crt 公钥、key私钥复制到验证中,发现认证ok。这样便可实现防篡改。

 

 

5、总结


在实际环境中应该使用加密的token,而不该该使用临时令牌。以及尽可能设置token的过时时间短,以及刷新token的机制,这样能够尽量的保护token以及数据安全。

 

asp.net core 交流群:787464275 欢迎加群交流
若是您认为这篇文章还不错或者有所收获,您能够点击右下角的【推荐】按钮精神支持,由于这种支持是我继续写做,分享的最大动力!

做者:LouieGuo
声明:原创博客请在转载时保留原文连接或者在文章开头加上本人博客地址,如发现错误,欢迎批评指正。凡是转载于本人的文章,不能设置打赏功能,若有特殊需求请与本人联系!

微信公众号:欢迎关注                                                 QQ技术交流群: 欢迎加群

                

LouieGuo