IDS4证书生成
一、概述
在IdentityServer4中有两种令牌,一个是JWT和Reference Token,在IDS4中默认用的是JWT,那么这两者有什么区别呢?
二、JWT与Reference Token的区别
1、JWT
JWT不可撤回。JWT令牌是一个自包含的访问令牌 - 它是一个带有声明和过期的受保护数据结构。一旦API了解了密钥材料,它就可以验证自包含的令牌,而无需与发行者进行通信。这使得JWT难以撤销。它们将一直有效,直到它们过期。JWT常被用于前后端分离,可以和 Restful API 配合使用,常用于构建身份认证机制,一个 JWT 实际上就是一个字符串,它包含了使用.分隔的三部分: Header 头部 Payload 负载 Signature 签名。在这个三个部分中最关键的就是signature。signature被用来确认JWT信息的发送者是谁,并保证信息没有被篡改,使用header中指定的算法将编码后的header、编码后的payload、一个secret进行加密。因此签名算法推荐使用RSA或ECDSA非对称加密算法。
JWT特点:
- JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
- 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输
- jwt去中心化的思想:api资源收到第一个请求之后,会去id4服务器获取公钥,然后用公钥验证token是否合法,如果合法进行后面的有效性验证。有且只有第一个请求才会去id4服务器请求公钥,后面的请求都会用第一次请求的公钥来验证,这也是jwt去中心化验证的思想。(注:如果签名证书发生改变则需要重启有请求ids4服务器的资源服务器。)
- JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
2、Reference Token
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还是非常棒的,毕竟与服务器交互的资源还是非常的昂贵的。
三、交互流程图
资源服务器在第一次解析AccessToken的时候会先到授权服务器获取配置数据(例如会访问:http://localhost:5000/.well-known/openid-configuration 获取配置的,http://localhost:5000/.well-known/openid-configuration/jwks 获取jwks)),之后解析AccessToken都会使用第一次获取到的配置数据,因此如果授权服务的配置更改了(加密证书等等修改了),那么应该重启资源服务器使之重新获取新的配置数据。
1、API使用JWT与认证中心的交互流程图
2、API使用Reference Token与认证中心的交互流程图
四、JWT中使用RSA加密
在说明JWT使用RSA加密之前我们先来比较一下其他的加密算法
1、HS256与RS256的区别
HS256 使用密钥生成固定的签名,RS256 使用成非对称进行签名。简单地说,HS256 必须与任何想要验证 JWT的 客户端或 API 共享秘密。即 如下图
RS256 生成非对称签名,这意味着必须使用私钥来签签名 JWT,并且必须使用对应的公钥来验证签名。与对称算法不同,使用 RS256 可以保证服务端是 JWT 的签名者,因为服务端是唯一拥有私钥的一方。这样做将不再需要在许多应用程序之间共享私钥。
五、生成证书
1、前言
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTemporarySigningCredential();
IDS4提供了以上两种临时证书生成的方案,既然有提供了生成证书的方案,为什么还要自己生成证书呢?原因如下:
- IDS4项目启动时,AddDeveloperSigningCredential或AddTemporarySigningCredential都会创建一个新的临时证书,这时候就会导致一个问题,重启之前生成的
access_token
,在重启之后,就不适用了,因为证书改变了,对应的加密方式也改变了,所以,就会出现下面这个问题:
- IDS4项目启动时, AddDeveloperSigningCredential或AddTemporarySigningCredential都会创建一个新的临时证书,它默认会存到硬盘上,但是这个方法只适合用于IDS4在单机运行的场景,如果是负载集群中,每台服务器上随机产生的证书都是不一样的。
综合以上两点,所以在生产环境我们还是要生成一个统一的证书。然后使用AddSigningCredential()方法将证书注入程序。
2、使用OpenSSL创建证书(Windows)
- 安装OpenSSL工具 ,官网下载地址:https://slproweb.com/products/Win32OpenSSL.html
- 下载完成后,双击exe傻瓜式完成安装,将安装的bin目录加入到系统环境变量
- 管理员身份打开cmd,输入下面命令:
openssl req -newkey rsa:2048 -nodes -keyout cas.clientservice.key -x509 -days 365 -out cas.clientservice.cer
- 如上图,根据提示输入相应的注册信息。执行上面命令之后,我们可以在C:\Users\lenovo目录下面找到cas.clientservice.cer和cas.clientservice.key两个文件:
- 下面的命令是将生成的证书和Key封装成一个文件,以便IDS4可以使用它们去正确地签名tokens,文件会生成在CMD执行目录“C:\Users\lenovo”中。
openssl pkcs12 -export -in cas.clientservice.cer -inkey cas.clientservice.key -out IS4.pfx
IS4.pfx是证书名称,可以自己修改,中途会提示让你输入Export Password,这个password在IS4中会用到,需要记下来。
3、项目中配置证书
- 拷贝生成的证书,放到认证/授权服务器项目中。证书属性改为始终复制。
- 在appsetting.json 配置文件配置如下信息:
- 在starup.cs中ConfigureServices方法中配置如下即可。