|
@@ -0,0 +1,219 @@
|
|
|
+package com.abi.qms.platform.infrastructure.util;
|
|
|
+
|
|
|
+
|
|
|
+import com.abi.base.foundation.exception.BusinessException;
|
|
|
+import com.abi.qms.platform.dao.entity.UserInfo;
|
|
|
+import com.auth0.jwt.JWT;
|
|
|
+import com.auth0.jwt.JWTVerifier;
|
|
|
+import com.auth0.jwt.algorithms.Algorithm;
|
|
|
+import com.auth0.jwt.exceptions.AlgorithmMismatchException;
|
|
|
+import com.auth0.jwt.exceptions.InvalidClaimException;
|
|
|
+import com.auth0.jwt.exceptions.TokenExpiredException;
|
|
|
+import com.auth0.jwt.interfaces.Claim;
|
|
|
+import com.auth0.jwt.interfaces.DecodedJWT;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+
|
|
|
+import java.security.interfaces.RSAPrivateKey;
|
|
|
+import java.security.interfaces.RSAPublicKey;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+
|
|
|
+import static com.abi.qms.platform.infrastructure.constant.RsaKey.RSA_PRIVATE_KEY;
|
|
|
+import static com.abi.qms.platform.infrastructure.constant.RsaKey.RSA_PUBLIC_KEY;
|
|
|
+import static com.abi.qms.platform.runner.CustomApplicationRunner.globalRsaKeyMap;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @className: com.abi.crm.infrastructure.utils-> JwtTokenUtils
|
|
|
+ * @description:
|
|
|
+ * @author: Marko.W
|
|
|
+ * @createDate: 2021-05-17 18:52
|
|
|
+ * @version: 1.0
|
|
|
+ * @todo:
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class JwtTokenUtils{
|
|
|
+
|
|
|
+ //默认两个小时过期
|
|
|
+ private Long expired = 7200L;
|
|
|
+
|
|
|
+
|
|
|
+ public static Boolean checkToken(String token){
|
|
|
+ try{
|
|
|
+ JWTVerifier jwtVerifier = JWT.require(Algorithm.RSA512((RSAPublicKey)globalRsaKeyMap.get(RSA_PUBLIC_KEY),
|
|
|
+ (RSAPrivateKey)globalRsaKeyMap.get(RSA_PRIVATE_KEY))).build();
|
|
|
+ jwtVerifier.verify(token);
|
|
|
+ return true;
|
|
|
+ }catch (Exception e){
|
|
|
+ log.info("token校验失败",e);
|
|
|
+ throw new BusinessException(401,"token认证失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据console端user用户生成token信息
|
|
|
+ * @param user
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String getToken(UserInfo user){
|
|
|
+ try {
|
|
|
+ String token = JWT.create()
|
|
|
+ .withKeyId(UUIDutils.getUUID())
|
|
|
+ .withExpiresAt(new Date(1721395275632L))
|
|
|
+ .withAudience(user.getId().toString())
|
|
|
+ .withClaim("userId",user.getId())
|
|
|
+ .withClaim("userName",user.getUserName())
|
|
|
+ .withClaim("roles","")
|
|
|
+ .sign(Algorithm.RSA512((RSAPublicKey)globalRsaKeyMap.get(RSA_PUBLIC_KEY),
|
|
|
+ (RSAPrivateKey)globalRsaKeyMap.get(RSA_PRIVATE_KEY)));
|
|
|
+ return token;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("生成token异常",e);
|
|
|
+ throw new BusinessException(500,"生成token异常");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private static void verifyAlgorithm(DecodedJWT jwt, Algorithm expectedAlgorithm) throws AlgorithmMismatchException {
|
|
|
+ if (!expectedAlgorithm.getName().equals(jwt.getAlgorithm())) {
|
|
|
+ throw new AlgorithmMismatchException("The provided Algorithm doesn't match the one defined in the JWT's Header.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void verifyClaims(DecodedJWT jwt, Map<String, Object> claims) throws TokenExpiredException, InvalidClaimException {
|
|
|
+ Iterator var3 = claims.entrySet().iterator();
|
|
|
+
|
|
|
+ while(var3.hasNext()) {
|
|
|
+ Map.Entry<String, Object> entry = (Map.Entry)var3.next();
|
|
|
+ String var5 = (String)entry.getKey();
|
|
|
+ byte var6 = -1;
|
|
|
+ switch(var5.hashCode()) {
|
|
|
+ case 96944:
|
|
|
+ if (var5.equals("aud")) {
|
|
|
+ var6 = 0;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 100893:
|
|
|
+ if (var5.equals("exp")) {
|
|
|
+ var6 = 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 104028:
|
|
|
+ if (var5.equals("iat")) {
|
|
|
+ var6 = 2;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 104585:
|
|
|
+ if (var5.equals("iss")) {
|
|
|
+ var6 = 4;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 105567:
|
|
|
+ if (var5.equals("jti")) {
|
|
|
+ var6 = 5;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 108850:
|
|
|
+ if (var5.equals("nbf")) {
|
|
|
+ var6 = 3;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 114240:
|
|
|
+ if (var5.equals("sub")) {
|
|
|
+ var6 = 6;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ switch(var6) {
|
|
|
+ case 0:
|
|
|
+ this.assertValidAudienceClaim(jwt.getAudience(), (List)entry.getValue());
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ this.assertValidDateClaim(jwt.getExpiresAt(), (Long)entry.getValue(), true);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ this.assertValidDateClaim(jwt.getIssuedAt(), (Long)entry.getValue(), false);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ this.assertValidDateClaim(jwt.getNotBefore(), (Long)entry.getValue(), false);
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ this.assertValidStringClaim((String)entry.getKey(), jwt.getIssuer(), (String)entry.getValue());
|
|
|
+ break;
|
|
|
+ case 5:
|
|
|
+ this.assertValidStringClaim((String)entry.getKey(), jwt.getId(), (String)entry.getValue());
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ this.assertValidStringClaim((String)entry.getKey(), jwt.getSubject(), (String)entry.getValue());
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ this.assertValidClaim(jwt.getClaim((String)entry.getKey()), (String)entry.getKey(), entry.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertValidClaim(Claim claim, String claimName, Object value) {
|
|
|
+ boolean isValid = false;
|
|
|
+ if (value instanceof String) {
|
|
|
+ isValid = value.equals(claim.asString());
|
|
|
+ } else if (value instanceof Integer) {
|
|
|
+ isValid = value.equals(claim.asInt());
|
|
|
+ } else if (value instanceof Long) {
|
|
|
+ isValid = value.equals(claim.asLong());
|
|
|
+ } else if (value instanceof Boolean) {
|
|
|
+ isValid = value.equals(claim.asBoolean());
|
|
|
+ } else if (value instanceof Double) {
|
|
|
+ isValid = value.equals(claim.asDouble());
|
|
|
+ } else if (value instanceof Date) {
|
|
|
+ isValid = value.equals(claim.asDate());
|
|
|
+ } else if (value instanceof Object[]) {
|
|
|
+ List<Object> claimArr = Arrays.asList((Object[])claim.as(Object[].class));
|
|
|
+ List<Object> valueArr = Arrays.asList((Object[])((Object[])value));
|
|
|
+ isValid = claimArr.containsAll(valueArr);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isValid) {
|
|
|
+ throw new InvalidClaimException(String.format("The Claim '%s' value doesn't match the required one.", claimName));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertValidStringClaim(String claimName, String value, String expectedValue) {
|
|
|
+ if (!expectedValue.equals(value)) {
|
|
|
+ throw new InvalidClaimException(String.format("The Claim '%s' value doesn't match the required one.", claimName));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertValidDateClaim(Date date, long leeway, boolean shouldBeFuture) {
|
|
|
+ Date today = new Date();
|
|
|
+ today.setTime((long)Math.floor((double)(today.getTime() / 1000L * 1000L)));
|
|
|
+ if (shouldBeFuture) {
|
|
|
+ this.assertDateIsFuture(date, leeway, today);
|
|
|
+ } else {
|
|
|
+ this.assertDateIsPast(date, leeway, today);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertDateIsFuture(Date date, long leeway, Date today) {
|
|
|
+ today.setTime(today.getTime() - leeway * 1000L);
|
|
|
+ if (date != null && today.after(date)) {
|
|
|
+ throw new TokenExpiredException(String.format("The Token has expired on %s.", date));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertDateIsPast(Date date, long leeway, Date today) {
|
|
|
+ today.setTime(today.getTime() + leeway * 1000L);
|
|
|
+ if (date != null && today.before(date)) {
|
|
|
+ throw new InvalidClaimException(String.format("The Token can't be used before %s.", date));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertValidAudienceClaim(List<String> audience, List<String> value) {
|
|
|
+ if (audience == null || !audience.containsAll(value)) {
|
|
|
+ throw new InvalidClaimException("The Claim 'aud' value doesn't contain the required audience.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|