之前在Spring Security 实战干货系列中我使用了 Spring 官方提供的spring-security-jwt作为JWT的实现。目前该工具包已经不再维护,而且对于最新推出的Spring Security OAuth2 ClientSpring Authorization Server都不是特别的兼容。所以抽了两天时间结合这两个新依赖重新实现了 JWT。

Nimbus 库

在目前最新的Spring Security中默认使用了Nimbus的 JOSE 库nimbus-jose-jwt。这个库目前是 JOSE 最常用的类库之一,大部分的改造工作都是围绕这个库开展的。

改造的过程分享

流程上跟 Spring Security 实战干货大致是一样的。

加载证书

证书依然使用 keytool 生成 2048 长度的 RSA 密钥。

这里之前使用了比较“暴力”的方式直接读取 KeyStore 然后使用公私钥,本次将 KeyStore 加载的证书转变为 JOSE 规范中的 JWK(Json Web Key)。

JWT

JWT 在 Spring Security 中被定义为org.springframework.security.oauth2.jwt.Jwt对象,对于 JWT 的操作可以抽象为两个方面。

生成 JWT

首先就是生成 JWT。目前的 Spring Security 本身是不提供这个能力的,只有在孵化中的Spring Authorization Server提供了生成 JWT 的抽象接口JwtEncoder

@FunctionalInterface
public interface JwtEncoder {Jwt encode(JoseHeader headers, JwtClaimsSet claims) throws JwtEncodingException;
}

JWT 的HeaderClaims也被相应地抽象为JoseHeaderJwtClaimsSet

于是我使用NimbusJwtEncoder进行了实现,其实是搬运了Spring Authorization Server的实现。当然也不是原版照搬,只是保证了门面一致,这样后续如果这个项目成熟了之后我们就可以无缝兼容了。

解析 JWT

既然有JwtEncoder必然有JwtDecoder。这个在Spring Security OAuth2 Client中是提供实现的,同样对其稍微加以改造。另外这个解码器不但负责将 JWT 字符串解析为 JWT 对象,它还承担了校验功能,这里有一个委托校验器DelegatingOAuth2TokenValidator,我们可以灵活定制来执行多个 JWT 校验策略。

Token 对

我们都知道通常 JWT 中的 Token 都是成对出现的。之前只是简单用一个类来封装了accessTokenrefreshToken的字符串形态。这次使用了spring ecurity oauth2 core提供的OAuth2AccessTokenResponse:

public final class OAuth2AccessTokenResponse {private OAuth2AccessToken accessToken;private OAuth2RefreshToken refreshToken;private Map<String, Object> additionalParameters;
}

这个类表达的内容更加丰富和灵活。对应的 json:

{"accessToken": {"tokenValue": "eyJraWQiOiJmZWxvcmRjbiIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJhbGwiLCJhdWQiOiJyb290IiwiaXNzIjoiaHR0cHM6XC9cL2ZlbG9yZC5jbiIsInNjb3BlcyI6WyJST0xFX0FETUlOIiwiUk9MRV9BUFAiXSwiZXhwIjoxNjE2ODM4NTg4LCJpYXQiOjE2MTY4MzQ5ODgsImp0aSI6IjBiYTUwZjFhLTI0N2YtNDJlYi05NzZiLTkyZWM5NDg2YjA2MCJ9.dwUK4ZgqhalKWu5AA8ZqaHjD2WPerhiF8lmybZGAorbncWdfVk7iAKUdRZunUekZmab_FsVpwprWIQpqSLtp6tz28sI71gO2StEeye5Vv4JRZKys68q2LGOAqMVJnBisEl211b5ASHSlP1qleU_TDxO_rgems76ZFD-kc1KmyelsoiBhmT3aD2_A_3fUmH7mV0jnC0rHauzOpS0AWnuPJaXbGPqrWotkQ_oqly47jipfNsPl_PUY1urng1wSx4QyblS8UgK-n5wJABhSN550WlwNLuC10ZckbhE5gazM0mD86mA_Xepe7LY5rjGNvO-Cz9k44TaURnTdSBdyy_EOiQ","issuedAt": {"epochSecond": 1616834988,"nano": 891000000},"expiresAt": {"epochSecond": 1616838588,"nano": 891000000},"tokenType": {"value": "Bearer"},"scopes": ["ROLE_ADMIN","ROLE_APP"]},"refreshToken": {"tokenValue": "eyJraWQiOiJmZWxvcmRjbiIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJhbGwiLCJhdWQiOiJyb290IiwiaXNzIjoiaHR0cHM6XC9cL2ZlbG9yZC5jbiIsInNjb3BlcyI6WyJST0xFX0FETUlOIiwiUk9MRV9BUFAiXSwiaWF0IjoxNjE2ODM0OTg4LCJqdGkiOiI3N2RhODk3NC0xMjM0LTQ5NzctOWU1MS1hOGY2NTdjMzA2NjAifQ.O9YYxkevkrTke7GbK2R5LGphnJ9vd07yFSwPs2gEZ94ObPkIs1wJ5gvlNOIlni_BYMNO-nMB8TiX0w-RQSwo-sbVLqeUHqv6NEXXmPJiWVmXTFVJf2b6lqW5Re7clXGvkFMw14ptAF6cpThDEE5XF4eCI8CDKKPWqNxY-8NvokwIY3NMXB1ofuHHRqjMyVUwNjOv6eaTJFTwebPy6Saem9kvaL_X1v9Drok6azbg5DSP1zKnbVazTaOs4aBZd5Firib3r_BGXdaJWAgJKfpP61__muVdujgkppMVU8fC9pqfnb6IqEaAOIZ69lrezA1K0QFinOhgcC2YZFxFoLL-IQ","issuedAt": {"epochSecond": 1616834988,"nano": 891000000},"expiresAt": null},"additionalParameters": {}
}

总结

其它大致没有改变多少,尽可能保证了原来的味道,又能够兼容 Spring Security 未来的风格。在代码迭代的过程中,如何能够同时做到兼容和灵活?关键就在于是否制定了统一的入口抽象和出口抽象。如果你能够做到这一点,你的代码质量就会明显的提高很多。我是:码农小胖哥,多多关注,分享更多日常开发中的心得体会。

对应的 DEMO 可以公众号回复 newjwt 获取,尊重他人分享,和谐交流。

牛批!全自动发布jar到Maven中央仓库

2021-03-25

Spring Security 实战干货:5.4版本带来的新玩法

2021-03-23

今天给没用过Git的新人简单培训了一下

2021-03-22

忙里偷闲又把自己的JWT实现改进了一下相关推荐

  1. Java学习专栏!全网最牛!

    Java基础系列 001:<快速深入理解JDK动态代理原理> 002:<这可能是你见过最全面的HashMap解读> 003:<我敢打赌你一定没用过 Java 中的这个类! ...

  2. 基于 JWT + Refresh Token 的用户认证实践

    HTTP 是一个无状态的协议,一次请求结束后,下次在发送服务器就不知道这个请求是谁发来的了(同一个 IP 不代表同一个用户),在 Web 应用中,用户的认证和鉴权是非常重要的一环,实践中有多种可用方案 ...

  3. javadoc: 错误 - 格式错误的语言环境名称_ONLYOFFICE 5.6.0 : 这是一个错误修正版本,改进了德语、法语、意大利语、葡萄牙语和俄语的翻译等...

    ONLYOFFICE 5.6.0 从此版本开始,我们更改了DocumentServer的编号方案. 这是一个错误修正版本. 具有一系列新功能的下一个主要版本将是6.0.0 修正 所有编辑 •修复形状的 ...

  4. 如何简单的在 ASP.NET Core 中集成 JWT 认证?

    前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...

  5. Jwt Token 的刷新机制设计

    Jwt Token 的刷新机制设计 Intro 前面的文章我们介绍了如何实现一个简单的 Jwt Server,可以实现一个简单 Jwt 服务,但是使用 Jwt token 会有一个缺点就是 token ...

  6. IdentityServer4实战 - 谈谈 JWT Token 的安全策略

    一.前言 众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference Token,一种是 JWT Token .前者的特点是 Token 的有效与否是由 To ...

  7. oauth2和jwt_OAuth2,JWT,Open-ID Connect和其他令人困惑的事物

    oauth2和jwt 免责声明 如果觉得我必须从一个重要的免责声明开始这篇文章: 不要太相信我要说的话. 我之所以这样说,是因为我们正在讨论安全性. 而且, 当您谈论安全性时,除了100%正确的陈述外 ...

  8. OAuth2,JWT,Open-ID Connect和其他令人困惑的事物

    免责声明 如果觉得我必须从一个重要的免责声明开始这篇文章: 不要太相信我要说的话. 我之所以这样说,是因为我们正在讨论安全性. 而且, 当您谈论安全性时,除了100%正确的陈述外,还有冒任何其他风险的 ...

  9. 《深入理解 Spring Cloud 与微服务构建》第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统 文章目录 <深入理解 Spring Cl ...

最新文章

  1. python3统一为什么类型_Python3 基本数据类型
  2. iOS开展——全球应对MotionEvent
  3. Flex4项目html-template文件夹解析
  4. android token机制_你真的了解16.6ms刷新机制吗?
  5. atom配置python环境_Python编程:用VScode配置Python开发环境
  6. VC++控件加载BMP图片(静态和动态方式)
  7. python爬关键词百度指数_Python爬虫爬取百度指数的关键词搜索指数教程
  8. 积累分布用例-洛伦兹曲线和随机游走
  9. 默纳克系统服务器怎么查故障,默纳克查历史故障
  10. 第19篇:关于近期cs服务端被反打的原因分析
  11. 基于51单片机的DHT11传感器
  12. 工程数学 傅里叶变换 狄拉克函数
  13. Multisim 13-电子线路实验
  14. 深度解析小米净水器不能接管线机的问题
  15. 多分类问题中sklearn的RFECV指定scoring函数
  16. hilbert算法的c语言实现,关于希尔伯特变换的 c语言实现
  17. 项目实施管理之项目调研
  18. 百度推出清风算法,SEO的标题该如何优化?
  19. 网络菜鸟把网络老鸟急死了
  20. python图形库哪个好_Python下的图像处理库,你要选哪个?

热门文章

  1. PyCharm快捷键(替换和查找)
  2. 【论文笔记_知识蒸馏_2022】Dynamic Rectification Knowledge Distillation
  3. win7提权system与后门
  4. 霍常亮教你开发淘宝客app第3节
  5. 如何在 Lightly 用 JavaScript 制作俄罗斯方块游戏
  6. [leetcode] 77. Combinations @ python
  7. 基于51单片机的智能护眼台灯设计proteus仿真原理图PCB
  8. SAP 发货成本中心
  9. JDK内置工具之appletviewer
  10. Cris 的 Python日记(一):基础语法