JwtUtils.java 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package com.genersoft.iot.vmp.conf.security;
  2. import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
  3. import com.genersoft.iot.vmp.service.IUserService;
  4. import com.genersoft.iot.vmp.storager.dao.dto.User;
  5. import org.jose4j.jwk.RsaJsonWebKey;
  6. import org.jose4j.jwk.RsaJwkGenerator;
  7. import org.jose4j.jws.AlgorithmIdentifiers;
  8. import org.jose4j.jws.JsonWebSignature;
  9. import org.jose4j.jwt.JwtClaims;
  10. import org.jose4j.jwt.NumericDate;
  11. import org.jose4j.jwt.consumer.ErrorCodes;
  12. import org.jose4j.jwt.consumer.InvalidJwtException;
  13. import org.jose4j.jwt.consumer.JwtConsumer;
  14. import org.jose4j.jwt.consumer.JwtConsumerBuilder;
  15. import org.jose4j.lang.JoseException;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;
  18. import org.springframework.beans.factory.InitializingBean;
  19. import org.springframework.stereotype.Component;
  20. import javax.annotation.Resource;
  21. import java.time.LocalDateTime;
  22. import java.time.ZoneOffset;
  23. @Component
  24. public class JwtUtils implements InitializingBean {
  25. private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
  26. public static final String HEADER = "access-token";
  27. private static final String AUDIENCE = "Audience";
  28. private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae";
  29. /**
  30. * token过期时间(分钟)
  31. */
  32. public static final long expirationTime = 30 * 24 * 60;
  33. private static RsaJsonWebKey rsaJsonWebKey;
  34. private static IUserService userService;
  35. @Resource
  36. public void setUserService(IUserService userService) {
  37. JwtUtils.userService = userService;
  38. }
  39. @Override
  40. public void afterPropertiesSet() {
  41. try {
  42. rsaJsonWebKey = generateRsaJsonWebKey();
  43. } catch (JoseException e) {
  44. logger.error("生成RsaJsonWebKey报错。", e);
  45. }
  46. }
  47. /**
  48. * 创建密钥对
  49. * @throws JoseException JoseException
  50. */
  51. private RsaJsonWebKey generateRsaJsonWebKey() throws JoseException {
  52. // 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
  53. RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
  54. // 给JWK一个密钥ID
  55. rsaJsonWebKey.setKeyId(keyId);
  56. return rsaJsonWebKey;
  57. }
  58. public static String createToken(String username) {
  59. try {
  60. /*
  61. * “iss” (issuer) 发行人
  62. * “sub” (subject) 主题
  63. * “aud” (audience) 接收方 用户
  64. * “exp” (expiration time) 到期时间
  65. * “nbf” (not before) 在此之前不可用
  66. * “iat” (issued at) jwt的签发时间
  67. */
  68. JwtClaims claims = new JwtClaims();
  69. claims.setGeneratedJwtId();
  70. claims.setIssuedAtToNow();
  71. // 令牌将过期的时间 分钟
  72. claims.setExpirationTimeMinutesInTheFuture(expirationTime);
  73. claims.setNotBeforeMinutesInThePast(0);
  74. claims.setSubject("login");
  75. claims.setAudience(AUDIENCE);
  76. //添加自定义参数,必须是字符串类型
  77. claims.setClaim("userName", username);
  78. //jws
  79. JsonWebSignature jws = new JsonWebSignature();
  80. //签名算法RS256
  81. jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
  82. jws.setKeyIdHeaderValue(keyId);
  83. jws.setPayload(claims.toJson());
  84. jws.setKey(rsaJsonWebKey.getPrivateKey());
  85. //get token
  86. return jws.getCompactSerialization();
  87. } catch (JoseException e) {
  88. logger.error("[Token生成失败]: {}", e.getMessage());
  89. }
  90. return null;
  91. }
  92. public static String getHeader() {
  93. return HEADER;
  94. }
  95. public static JwtUser verifyToken(String token) {
  96. JwtUser jwtUser = new JwtUser();
  97. try {
  98. JwtConsumer consumer = new JwtConsumerBuilder()
  99. .setRequireExpirationTime()
  100. .setMaxFutureValidityInMinutes(5256000)
  101. .setAllowedClockSkewInSeconds(30)
  102. .setRequireSubject()
  103. //.setExpectedIssuer("")
  104. .setExpectedAudience(AUDIENCE)
  105. .setVerificationKey(rsaJsonWebKey.getPublicKey())
  106. .build();
  107. JwtClaims claims = consumer.processToClaims(token);
  108. NumericDate expirationTime = claims.getExpirationTime();
  109. // 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
  110. // 剩余时间 (秒)
  111. long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
  112. if (timeRemaining < 5 * 60) {
  113. jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
  114. } else {
  115. jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
  116. }
  117. String username = (String) claims.getClaimValue("userName");
  118. User user = userService.getUserByUsername(username);
  119. jwtUser.setUserName(username);
  120. jwtUser.setPassword(user.getPassword());
  121. jwtUser.setRoleId(user.getRole().getId());
  122. jwtUser.setUserId(user.getId());
  123. return jwtUser;
  124. } catch (InvalidJwtException e) {
  125. if (e.hasErrorCode(ErrorCodes.EXPIRED)) {
  126. jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
  127. } else {
  128. jwtUser.setStatus(JwtUser.TokenStatus.EXCEPTION);
  129. }
  130. return jwtUser;
  131. } catch (Exception e) {
  132. logger.error("[Token解析失败]: {}", e.getMessage());
  133. jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
  134. return jwtUser;
  135. }
  136. }
  137. }