授权服务的核心:授权访问令牌,OAuth 只要符合要求,2.0规范就不限制访问令牌内容的生成规则:
- 唯一性
- 不连续性
- 不可猜性
可灵活选择令牌形式:
- 但是没有内部结构 && 随机字符串不包含任何信息意义
- 也有内部结构 && 包含信息意义的字符串
在过去,生成令牌的方式是默认的随机字符串。而结构化令牌,目前使用最多的是JWT令牌。
1 简介JSON Web Token(JWT)是开放标准(RFC 7519)定义了一种紧凑、自包含的方式,作为JSON对象,在各方之间安全传输信息,结构化包装生成token。结构化的token可以被赋予丰富的含义,这与无意义的随机字符串形式的token最大区别。
2 JWT结构例如,eyJhbgcioiJiuzi1Niisinr5cici6ikpXVCJ9.G9lIiwiaWF0IjoxNTE2MjM5GMG4GRG9lIiwiaWF0IjoxNTE2MjM5GMJJzdWIOIxMJM0NTY3ODkwIiwibmMDIyfQ.SflKxwrJSKF2QT4fwpmeJf36pok6yJVc
https://jwt.io/网站解密
2.1 HEADER(头部)装载令牌类型及算法等信息:
- typ PAYLOAD的第二部分是JWT类型
- alg 表示使用HS256对称签名算法
代表一组数据:
- sub令牌的主体一般是资源所有者的唯一标志
- exp令牌过期时间戳
- iat令牌颁发的时间戳
PAYLOAD表示的一组数据允许我们自定义声明是JWT的标准声明。
2.3 SIGNATURE(签名)签名后的JWT整体结构是.
分割的三个部分:header.payload.signature
。JWT令牌直接用肉眼,看起来毫无意义。它被复制到 https://jwt.io/ 在线验证可以看到解码后的有意义数据。
SIGNATURE
签署JWT信息。
有了HEADER
和PAYLOAD
允许令牌携带信息在网络中传输,但在网络中传输此类信息是不安全的。必须加密签名,SIGNATURE
这是信息的签名结果。当受保护资源收到三方软件的签名时,需要验证令牌的签名是否合法。
由于授权服务颁发令牌,受保护资源服务应验证令牌。受保护资源调用授权服务提供的检验令牌服务的验证令牌方法称为令牌内部检查。
3.2 特点有时授权服务依赖DB,然后受保护的资源服务依赖DB,即“共享DB”。
在微服务架构下,不同的系统依赖服务而不是DB通信,如[授权服务]为[受保护的资源服务]提供RPC服务:
JWT令牌本身包含了以前依赖DB或RPC服务的信息,如用户授权软件等。
4 JWT实现方案JWT令牌后的通信方式:
授权服务发送令牌,受保护资源服务接令牌,然后开始分析令牌中包含的信息,无需查询DB或RPC调用。即实现令牌内部检查。
4.1 HMAC 流程Hash-based Message Authentication Code,基于哈希函数的信息认证码。通常使用共享密钥来计算和验证信息认证码来验证数据的完整性和真实性。
- 使用Base64算法编码header和payload,并使用“.串联成一个字符串
- 使用secret key在HMAC签名操作上一步获得的字符串,生成签名值
- Base64编码签名值,最终JWT由JWT的header和payload组成。
在验证JWT时,接收方应按照相同的流程计算签名值,并将其与JWT中的签名值进行比较。如果相同,则表明JWT有效。由于签名值的生成过程需要使用密钥,只有持有密钥的人才能正确计算签名值,以确保JWT的安全。
4.2 RSA 流程Rivest-Shamir-Adleman,也可用于数字签名的公钥加密算法。
基于两个大质量乘积,很难分解这个数学问题。公钥和私钥配对被广泛应用于网络安全、数字签名、电子商务等领域。
- 使用Base64算法编码header和payload,并使用“.串联成字符串
- 使用private Key在RSA签名操作上一步获得的字符串,生成签名值
- Base64编码签名值,与JWT的header和payload一起组成最终JWT。
接收方验证JWT时:
- 从JWT分析签名值
- 使用public key对JWT的header和payload进行RSA验证,以获得验证结果
- 将结果与JWT中的签名值进行比较,如果相同,则表明JWT是有效的
由于只有发行人拥有私钥,只有发行人才能正确签署JWT,任何人都可以使用公钥进行验证,以确保JWT的安全性和可信度。
5 为什么令牌要编码签名?授权服务发布JWT后给XX软件,XX拿着令牌要求受保护的资源服务,也就是我在微信官方账号的文章。显然,令牌应该在公共网站上传输。因此,在传输过程中,令牌应该做到:
- 编码,防乱码
- 为防止数据信息泄露,签名并加密。
jjwt 开源JWT工具包装Base64URL编码和对称HMAC、非对称RSA的一系列签名算法。使用它可以很容易地生成签名的JWT令牌,并分析JWT令牌。
1// 密钥2String sharedTokenSecret="hellooauthhellooauthhellooauthhellooauth";3Key key = new SecretKeySpec(sharedTokenSecret.getBytes(),4 SignatureAlgorithm.HS256.getJcaName());56// 生成JWT令牌7String jwts=8Jwts.builder()9 .setHeaderParams(headerMap)10 .setClaims(payloadMap)11 .signWith(key,SignatureAlgorithm.HS256)12 .compact()1314// JWT令牌15Jws分析<Claims> claimsJws =Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jwts);16Jwsheaderder header = claimsJws.getHeader();17Claims body = claimsJws.getBody();
6 优点6.1 计算代替存储
时间换空间。这种计算和结构化包装减少了“共享DB” 远程调用造成的网络传输性能损失可能会节省时间。
6.2 加密由于JWT令牌包含重要信息,因此传输过程必须要求密文传输,强制加密也保证了传输安全。
6.3 提高系统的可用性和可伸缩性JWT令牌通过“自编码”包含身份验证所需的信息,不需要额外存储在服务端,因此每个请求都是无状态对话。遵循无状态架构设计原则,提高系统的可用性和可伸缩性。
6.4 降低 AuthServer 压力在客户端获得令牌后,后续的资源服务器可以进行自验证,无需到AuthServer验证。
6.5 简化AuthServer无需维护和管理用户状态会话
7 缺点7.1 无状态和吊销不能两全两全两全不能在使用过程中修改令牌状态。例如,当我使用xx时,我可能无缘无故地修改了在公共账户平台上的密码,或者突然取消了对xx的授权。此时,令牌状态应发生变化,相应的令牌无效。但在使用JWT时,每个发布的令牌都不会有服务端,也不会改变令牌状态。这意味着JWT令牌在有效期内将畅通无阻。
JWT令牌可以存储在Redis等分布式内存数据库中吗?NO!这违背了JWT的意义 - 将信息结构化存储在令牌本身中。通常有两种方案:
- 将每次生成JWT令牌时的密钥粒度降低到用户级别,即一个用户和一个密钥。当用户取消授权或修改密码时,密钥可以一起修改。该方案通常需要支持单独的密钥管理服务
- 在不提供用户主动取消授权的环境中,如果只考虑修改密码场景,用户密码可以作为JWT的密钥。这也是用户粒度。这样,用户修改密码就相当于修改密钥。
随 claims 增加和增加。
8 令牌的生命周期令牌有[有效期],但JWT可以将有效期的信息存储在自己的结构中。
OAuth 2.0令牌生命周期:
- 令牌自然过期
- 该过程不排除主动销毁令牌的可能性。例如,如果令牌泄露,授权服务将使令牌失效。
- 访问令牌失效后,可使用刷新令牌请求新令牌,提高用户使用三方软件的体验。
- 让XX等三方软件主动启动令牌失效请求,然后授权服务在收到请求后立即失效。什么时候需要这个机制?
- 例如,用户和三方软件之间存在订单关系:如果我购买xx软件,当我授权的代码到期或退订时未到期时,我需要这样的代码退回协议,以支持xx主动发起代码失效请求。作为一个开放的平台,负责任的三方软件也应遵守这样的代码退出协议。
OAuth 2.0 核心是授权服务,没有令牌就没有OAuth,令牌表示授权后的结果。令牌在OAuth 第三方软件在2.0系统中是不透明的。授权服务和受保护资源服务需要关注令牌。
- JWT默认不加密,但也可以加密。生成原始 Token 之后,密钥可以再次加密
- JWT不加密时,不能将秘密数据写入JWT
- JWT不仅可以用于认证,还可以用于交换信息。有效使用 JWT,可以减少服务器查询数据库的次数
- JWT 最大的缺点是服务器没有保存 session 因此,在使用过程中不能废除某种状态 token,或者更改 token 权限。也就是一旦 JWT 除非服务器部署了额外的逻辑,否则签发将在到期前始终有效
- JWT本身包含认证信息,一旦泄露,任何人都可以获得令牌的所有权限。为减少盗窃,JWT 有效期应设置相对较短。对于一些重要的权限,用户在使用时应再次进行认证
- 为减少盗用,JWT 不应使用 HTTP 协议明码传输,应使用 HTTPS 协议传输
参考
- JSON Web Token 入门教程
- OAuth 如何在2.0中使用JWT结构化令牌?
- https://tools.ietf.org/html/rfc6749#section-4.4