第一步:创建SpringBoot项目

  • 添加依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.2</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.2</version><scope>runtime</scope>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
  • 修改配置文件application.yml
jwt:# 为JWT基础信息加密和解密的密钥,长度需要大于等于43# 在实际生产中通常不直接写在配置文件里面。而是通过应用的启动参数传递,并且需要定期修改secret: oQZSeguYloAPAmKwvKqqnifiQatxMEPNOvtwPsCLasd# JWT令牌的有效时间,单位秒,默认2周expiration: 1209600header: Authorizationprefix: hc

第二步:创建JWT工具类

@Slf4j
@Component
//@ConfigurationProperties(prefix = "jwt")
public class JwtUtil {/*** 携带JWT令牌的HTTP的Header的名称,在实际生产中可读性越差越安全*/@Getter@Value("${jwt.header}")private String header;/*** 为JWT基础信息加密和解密的密钥* 在实际生产中通常不直接写在配置文件里面。而是通过应用的启动参数传递,并且需要定期修改。*/@Value("${jwt.secret}")private String secret;/*** JWT令牌的有效时间,单位秒* - 默认2周*/@Value("${jwt.expiration}")private Long expiration;/*** SecretKey 根据 SECRET 的编码方式解码后得到:* Base64 编码:SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString));* Base64URL 编码:SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64URL.decode(secretString));* 未编码:SecretKey key = Keys.hmacShaKeyFor(secretString.getBytes(StandardCharsets.UTF_8));*/private static SecretKey getSecretKey(String secret) {byte[] encodeKey = Decoders.BASE64.decode(secret);return Keys.hmacShaKeyFor(encodeKey);}/*** 用claims生成token** @param claims 数据声明,用来创建payload的私有声明* @return token 令牌*/private String generateToken(Map<String, Object> claims) {SecretKey key = getSecretKey(secret);//SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); //两种方式等价// 添加payload声明JwtBuilder jwtBuilder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。.setId(UUID.randomUUID().toString())// iat: jwt的签发时间.setIssuedAt(new Date())// 你也可以改用你喜欢的算法,支持的算法详见:https://github.com/jwtk/jjwt#features// SignatureAlgorithm.HS256:指定签名的时候使用的签名算法,也就是header那部分.signWith(key, SignatureAlgorithm.HS256).setExpiration(new Date(System.currentTimeMillis() + this.expiration * 1000));String token = jwtBuilder.compact();return token;}/*** 生成Token令牌** @param userDetails 用户* @param id          用户编号* @return 令牌Token*/public String generateToken(UserDetails userDetails, String id) {Map<String, Object> claims = new HashMap<>();claims.put("userId", id);claims.put("sub", userDetails.getUsername());claims.put("created", new Date());return generateToken(claims);}/*** 从token中获取数据声明claim** @param token 令牌token* @return 数据声明claim*/public Claims getClaimsFromToken(String token) {try {SecretKey key = getSecretKey(secret);Claims claims = Jwts.parserBuilder().setSigningKey(key).parseClaimsJws(token).getBody();return claims;} catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | IllegalArgumentException e) {log.error("token解析错误", e);throw new IllegalArgumentException("Token invalided.");}}public String getUserId(String token) {return (String) getClaimsFromToken(token).get("userId");}/*** 从token中获取登录用户名** @param token 令牌* @return 用户名*/public String getSubjectFromToken(String token) {String subject;try {Claims claims = getClaimsFromToken(token);subject = claims.getSubject();} catch (Exception e) {subject = null;}return subject;}/*** 获取token的过期时间** @param token token* @return 过期时间*/public Date getExpirationFromToken(String token) {return getClaimsFromToken(token).getExpiration();}/*** 判断token是否过期** @param token 令牌* @return 是否过期:已过期返回true,未过期返回false*/public Boolean isTokenExpired(String token) {Date expiration = getExpirationFromToken(token);return expiration.before(new Date());}/*** 验证令牌:判断token是否非法** @param token       令牌* @param userDetails 用户* @return 如果token未过期且合法,返回true,否则返回false*/public Boolean validateToken(String token, UserDetails userDetails) {//如果已经过期返回falseif (isTokenExpired(token)) {return false;}String usernameFromToken = getSubjectFromToken(token);String username = userDetails.getUsername();return username.equals(usernameFromToken);}}

第三步:SpringSecurity配置文件注入PasswordEncoder

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

第四步:工具类测试

@SpringBootTest
public class JwtUtilTest {@Resourceprivate JwtUtil jwtUtil;@Resourceprivate PasswordEncoder passwordEncoder;@Testvoid fun() {System.out.println(passwordEncoder);SecretKey secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);System.out.println(secretKey);}//生成token@Testvoid generateToken() {//用户信息String encode = passwordEncoder.encode("1234");User user = new User("hc", encode, AuthorityUtils.createAuthorityList());String token = jwtUtil.generateToken(user, "202");System.out.println(token);}@Testvoid getClaimsFromToken() {//用户信息String encode = passwordEncoder.encode("1234");User user = new User("zhangsan", encode, AuthorityUtils.createAuthorityList());String token = jwtUtil.generateToken(user, "202");System.out.println(token);Claims claims = jwtUtil.getClaimsFromToken(token);System.out.println(claims);}@Testvoid getUserId() {String userId = jwtUtil.getUserId("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ6aGFuZ3NhbiIsImNyZWF0ZWQiOjE2NDE5Nzc3NjA5MTIsInVzZXJJZCI6IjIwMiIsImp0aSI6IjhkMzA0YmYwLTkwZmQtNGFlZC1iMWRkLWEwODE0M2RjMDEzYiIsImlhdCI6MTY0MTk3Nzc2MCwiZXhwIjoxNjQzMTg3MzYwfQ.LJCI5gxEdZYlqfnuS5V5SxwZv-ul411LjGZvbYWQseI");System.out.println(userId);}@Testvoid getSubjectFromToken() {//用户信息String encode = passwordEncoder.encode("1234");User user = new User("zhangsan", encode, AuthorityUtils.createAuthorityList());String token = jwtUtil.generateToken(user, "202");System.out.println(token);String username = jwtUtil.getSubjectFromToken(token);System.out.println(username);}@Testvoid getExpirationFromToken() {//用户信息String encode = passwordEncoder.encode("1234");User user = new User("zhangsan", encode, AuthorityUtils.createAuthorityList());String token = jwtUtil.generateToken(user, "202");System.out.println(token);Date date = jwtUtil.getExpirationFromToken(token);System.out.println(new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(date));}@Testvoid isTokenExpired() {//用户信息String encode = passwordEncoder.encode("1234");User user = new User("zhangsan", encode, AuthorityUtils.createAuthorityList());String token = jwtUtil.generateToken(user, "202");System.out.println(token);Boolean res = jwtUtil.isTokenExpired(token);System.out.println(res);}@Testvoid validateToken() {//用户信息String encode = passwordEncoder.encode("1234");User user = new User("zhangsan", encode, AuthorityUtils.createAuthorityList());String token = jwtUtil.generateToken(user, "202");System.out.println(token);User user2 = new User("zhangsan", "", AuthorityUtils.createAuthorityList());Boolean res = jwtUtil.validateToken(token, user2);System.out.println(res);}//模拟篡改@Testvoid fake() {// 将我改成你生成的token的第一段(以.为边界)String encodedHeader = "eyJhbGciOiJIUzI1NiJ9";// 测试4: 解密Headerbyte[] header = Base64.decodeBase64(encodedHeader.getBytes());System.out.println(new String(header));// 将我改成你生成的token的第二段(以.为边界)String encodedPayload = "eyJpZCI6IjEiLCJpYXQiOjE1NjU1ODk1NDEsImV4cCI6MTU2Njc5OTE0MX0";// 测试5: 解密Payloadbyte[] payload = Base64.decodeBase64(encodedPayload.getBytes());System.out.println(new String(payload));//用户信息String encode = passwordEncoder.encode("1234");User user = new User("zhangsan", encode, AuthorityUtils.createAuthorityList());// 测试6: 这是一个被篡改的token,因此会报异常,说明JWT是安全的jwtUtil.validateToken("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEiLCJpYXQiOjE1NjU1ODk3MzIsImV4cCI6MTU2Njc5OTMzMn0.nDv25ex7XuTlmXgNzGX46LqMZItVFyNHQpmL9UQf-aUx", user);}}

SpringBoot+SpringSecurity系列 :JWT 工具类相关推荐

  1. SpringBoot + SpringSecurity + Mybatis-Plus + JWT + Redis 实现分布式系统认证和授权(刷新Token和Token黑名单)

    1. 前提   本文在基于SpringBoot整合SpringSecurity实现JWT的前提中添加刷新Token以及添加Token黑名单.在浏览之前,请查看博客:   SpringBoot + Sp ...

  2. 项目添加JWT工具类

    在common_utils模块中添加jwt工具依赖 在pom中添加 <dependencies><!-- JWT--><dependency><groupId ...

  3. JWT的讲解以及JJWT的使用(另附JWT工具类)

    0. 前言 关于JWT的文章网上已经多如牛毛了,但是相信很多同学学的还是云里雾里,所以在我学习JWT之后尽量用最简洁的描述写下这篇文章用于日后复习,与此同时也希望可以帮助同学们共同进步,如果文章对你有 ...

  4. JWT|概述|JWT结构|JWT在java中的使用|JWT工具类的封装|JWT在springboot中的使用|JWT与拦截器的配合

    JWT ! 前记: 官网:https://jwt.io/ jwt有人说是用计算力换空间(相对于session) 小程序后台要求全部用springboot实现..登录状态的管理:本来想用自己随便生成UU ...

  5. java.awt.font 宋体,SpringBoot项目集成字体工具类

    场景:采用JasperReport生成报表时,若将模版中的字体配置成宋体时.部署在不同的系统上时,可能会出现中文乱码的情况,也可以适用于其他任何需要单独配置字体的第三方库. 首先,你可以给部署的服务器 ...

  6. SpringBoot项目集成字体工具类

    场景:采用JasperReport生成报表时,若将模版中的字体配置成宋体时.部署在不同的系统上时,可能会出现中文乱码的情况,也可以适用于其他任何需要单独配置字体的第三方库. 首先,你可以给部署的服务器 ...

  7. SpringBoot JWT工具类完整代码

  8. SpringBoot+SpringSecurity+RBAC+JWT实现动态权限框架

    一.创建数据库表 DROP TABLE IF EXISTS luo_admin; CREATE TABLE luo_admin ( id bigint(20) NOT NULL AUTO_INCREM ...

  9. springboot+springsecurity+mybatis+jwt实现单点登录(详细到爆了)

    2021年奉上我最喜欢的一句话:愿你孤独的努力都有回报,愿你前行的路上有人陪伴.加油

最新文章

  1. 【福利贴】拿去!1024凑个整!
  2. PPT 图片python处理
  3. blob字段乱码怎么处理_金九银十,你准备好了吗?没点Python面试题干货怎么行?(一)...
  4. python vtk_VTK在python环境下的安装和调用
  5. RHCS集群原理概述
  6. 【剑指offer】面试题25:合并两个排序的链表(Java 实现)
  7. Redis发布订阅机制
  8. html自动播放视频不可用muted,html5_videoaudio的autoplay属性失效的解决方法
  9. 正则表达式去除html标签
  10. Mac安装jdk并配置环境变量
  11. 对未来国产操作系统的期望
  12. 惠普bios硬重置_惠普BIOS密码重置工具|惠普笔记本BIOS密码重置工具 - 万方软件下载站...
  13. seo模拟点击软件_百度搜索SEO优化算法揭秘
  14. excel导出设置自动列宽
  15. 基于共识算法和区块链模拟实现超级账本
  16. 51nod 2591 最终讨伐
  17. 持久内存指令(PMDK)简介
  18. Anaconda的升级与卸载
  19. 深度原创丨当互联网巨头从云端“抄底” BI 和大数据...
  20. Android之targetSdkVersion详解

热门文章

  1. htons和ntohs没有区别
  2. sqlmap 连接mysql_sqlmap连接Mysql实现getshell(原创)
  3. 为什么不使用ServiceStack.Redis dll ?而使用NewLife.Redis、NewLife.Core ?使用NewLife的Redis工具类
  4. Heat equation
  5. 上海几个医院入职体检费用及报告出来的时间
  6. Baby的创意新摄影-玩转杯子
  7. 高内聚低耦合设计原则
  8. 为啥 redis 使用 跳表 (skiplist) 而不是使用 red-black?
  9. UnityWebRequest替代WWW
  10. 辽宁启迪电商:拼多多买家催发货怎么办?