Commit 56656fc9f0cd6c036f77553e8208959eb4c78a72

Authored by 谭毅彬
1 parent ca530b14

API接口TOKEN认证完成

Signed-off-by: TanYibin <5491541@qq.com>
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/acs/controller/AcsController.java
... ... @@ -6,8 +6,10 @@ import javax.annotation.Resource;
6 6 import javax.servlet.http.HttpServletRequest;
7 7  
8 8 import org.jeecg.common.api.vo.Result;
  9 +import org.jeecg.common.system.util.JwtUtil;
9 10 import org.jeecg.modules.wms.api.acs.entity.AcsStatus;
10 11 import org.jeecg.modules.wms.api.acs.service.IAcsService;
  12 +import org.jeecg.modules.wms.framework.aspectj.PassApiAuthentication;
11 13 import org.jeecg.modules.wms.framework.aspectj.lang.annotation.ApiLogger;
12 14 import org.jeecg.modules.wms.framework.controller.HuahengBaseController;
13 15 import org.jeecg.modules.wms.task.agvTask.service.IAgvTaskService;
... ... @@ -36,8 +38,6 @@ public class AcsController extends HuahengBaseController {
36 38 @ResponseBody
37 39 @PostMapping(value = "/testTokenCheck")
38 40 public Result<?> testTokenCheck(@RequestBody Map<String, String> paramMap, HttpServletRequest request) {
39   -
40   -
41 41 return new Result<>();
42 42 }
43 43  
... ...
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/framework/aspectj/ApiAuthenticationAspect.java
1 1 package org.jeecg.modules.wms.framework.aspectj;
2 2  
3 3 import java.lang.reflect.Method;
  4 +import java.util.Arrays;
4 5  
5 6 import javax.servlet.http.HttpServletRequest;
6 7  
... ... @@ -9,11 +10,22 @@ import org.aspectj.lang.annotation.Aspect;
9 10 import org.aspectj.lang.annotation.Before;
10 11 import org.aspectj.lang.annotation.Pointcut;
11 12 import org.aspectj.lang.reflect.MethodSignature;
  13 +import org.jeecg.modules.wms.framework.aspectj.dto.RSA256Key;
  14 +import org.jeecg.utils.HuahengJwtUtil;
  15 +import org.springframework.beans.factory.annotation.Autowired;
12 16 import org.springframework.scheduling.annotation.EnableAsync;
13 17 import org.springframework.stereotype.Component;
14 18 import org.springframework.web.context.request.RequestContextHolder;
15 19 import org.springframework.web.context.request.ServletRequestAttributes;
16 20  
  21 +import com.auth0.jwt.JWT;
  22 +import com.auth0.jwt.JWTVerifier;
  23 +import com.auth0.jwt.algorithms.Algorithm;
  24 +import com.auth0.jwt.exceptions.JWTVerificationException;
  25 +import com.auth0.jwt.interfaces.DecodedJWT;
  26 +
  27 +import cn.hutool.core.date.DatePattern;
  28 +import cn.hutool.core.date.DateUtil;
17 29 import lombok.extern.slf4j.Slf4j;
18 30  
19 31 /**
... ... @@ -27,10 +39,11 @@ import lombok.extern.slf4j.Slf4j;
27 39 @EnableAsync
28 40 public class ApiAuthenticationAspect {
29 41  
30   - @Pointcut("execution(* org.jeecg.modules.wms.api..*.*(..)) "
31   - + "&& (@annotation(org.springframework.web.bind.annotation.RequestMapping) "
32   - + "|| @annotation(org.springframework.web.bind.annotation.GetMapping) "
33   - + "|| @annotation(org.springframework.web.bind.annotation.PostMapping))")
  42 + @Autowired
  43 + private RSA256Key rsa256Key;
  44 +
  45 + @Pointcut("execution(* org.jeecg.modules.wms.api..*.*(..)) " + "&& (@annotation(org.springframework.web.bind.annotation.RequestMapping) "
  46 + + "|| @annotation(org.springframework.web.bind.annotation.GetMapping) " + "|| @annotation(org.springframework.web.bind.annotation.PostMapping))")
34 47 public void executeController() {}
35 48  
36 49 /**
... ... @@ -55,7 +68,14 @@ public class ApiAuthenticationAspect {
55 68 ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
56 69 HttpServletRequest request = attributes.getRequest();
57 70 String token = request.getHeader("token");
58   - log.info("开始校验Token:{}", token);
  71 + try {
  72 + Algorithm algorithm = Algorithm.RSA256(rsa256Key.getPublicKey(), rsa256Key.getPrivateKey());
  73 + JWTVerifier verifier = JWT.require(algorithm).withIssuer(HuahengJwtUtil.HUAHENG_SYSTEM_ID).build();
  74 + verifier.verify(token);
  75 + } catch (JWTVerificationException e) {
  76 + log.error("TOKEN认证失败:{}", e.getMessage());
  77 + throw e;
  78 + }
59 79 }
60 80  
61 81 /**
... ...
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/framework/aspectj/dto/ApiAuthentication.java 0 → 100644
  1 +package org.jeecg.modules.wms.framework.aspectj.dto;
  2 +
  3 +import java.util.Date;
  4 +
  5 +import org.jeecg.utils.HuahengJwtUtil;
  6 +
  7 +import cn.hutool.core.date.DatePattern;
  8 +import cn.hutool.core.date.DateUtil;
  9 +import lombok.Data;
  10 +
  11 +/**
  12 + * 接口认证Token生成对象
  13 + * @author TanYibin
  14 + * @createDate 2023年2月14日
  15 + */
  16 +@Data
  17 +public class ApiAuthentication {
  18 +
  19 + /** Token提供方 */
  20 + private String operator;
  21 +
  22 + /** Token使用方 */
  23 + private String audience; // 观众,相当于接受者
  24 +
  25 + /** Token签发方(WMS) */
  26 + private String issuer = HuahengJwtUtil.HUAHENG_SYSTEM_ID;
  27 +
  28 + /** 失效时间 */
  29 + private Date expireDateTime;
  30 +
  31 +}
... ...
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/framework/aspectj/dto/RSA256Key.java 0 → 100644
  1 +package org.jeecg.modules.wms.framework.aspectj.dto;
  2 +
  3 +import java.security.interfaces.RSAPrivateKey;
  4 +import java.security.interfaces.RSAPublicKey;
  5 +
  6 +import org.jeecg.utils.SecretKeyUtils;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import lombok.Data;
  10 +
  11 +@Data
  12 +@Component
  13 +public class RSA256Key {
  14 +
  15 + /** 第三方HTTP访问 公钥 */
  16 + private RSAPublicKey publicKey =
  17 + (RSAPublicKey)SecretKeyUtils.getPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmYcmhWzpgLgWVD0j+uTyFvQW0BBktYVJmTRQvLlrKt4CHnkfQ4Dn"
  18 + + "SLaRXCcJK/TGgAY0BtnaKUgFBqqmTI9l82tpxEWqYRzp4KGRLnVA6/igidYib0JeBWroI6Bs0wR43fkSXA8XG+n32bVbmMTKNa9IFUJCzICVTEjQzMQrSAwIDAQAB");
  19 +
  20 + /** 第三方HTTP访问 私钥 */
  21 + private RSAPrivateKey privateKey =
  22 + (RSAPrivateKey)SecretKeyUtils.getPrivateKey("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKZhyaFbOmAuBZUPSP65PIW9BbQEGS1hUmZNFC8uWsq"
  23 + + "3gIeeR9DgOdItpFcJwkr9MaABjQG2dopSAUGqqZMj2Xza2nERaphHOngoZEudUDr+KCJ1iJvQl4FaugjoGzTBHjd+RJcDxcb6ffZtVuYxMo1r0gVQkLMgJVMSNDMxCtID"
  24 + + "AgMBAAECgYBhxluIMCVI+iKbqyTZVB/l8+PTGwl0qpmStr8iztnaASZODEzlya8Q/XNzFrAQA2TTQ7YKiKB2vqQwY8tNRab7jpR4t5WPApDVrMvjPfvqVvBsPzTYr2c08"
  25 + + "xMfqcj5HNzPLisb7Wvi7URSL4jIY/106lXN+9cJuMV0oDZzcAhaYQJBANdNMlSnzTDF8VQ7ETpzZQrF0UzlqKeKG0Pz/YeTXT4IjyBhzvaSOF3+hi1cWucrSU0xMUAR9F"
  26 + + "av+K1BlPTYW/MCQQDF1UqEAY7YGzpUZK311ECO12ysb0oMt2jTYMwmgPnfPZfctD6SlV3u/JtsgE+bN5dXwV0ktyfP/3vl395zGoWxAkEAt/bQMKGIpEoeILivyd/b0E6"
  27 + + "ivi/l4fIRxghu8y8plt29Xg/0xZ6+5yGaCJxHWAsWgQytZm9w9bk6pN/KpUNRnQJAbQS72oDNSdO/UhBlOOntZYnbTi7J3LYZoxpdhf5fNCFKFYqSTM7ZA8DamXEf7UY2"
  28 + + "NVrOTFROMTX1/dhfSojcEQJBALNxIrEP97uszxIc8oH2r7DfXzmhRMKuIvnBfmNe1TR" + "VLvh1G1SKIyCYUTStaQCFN0FcH//Fab+zPiAgDmXApWs=");
  29 +}
... ...
huaheng-wms-core/src/main/java/org/jeecg/utils/HuahengJwtUtil.java
1 1 package org.jeecg.utils;
2 2  
  3 +import java.util.Arrays;
3 4 import java.util.Date;
  5 +import java.util.UUID;
4 6  
5 7 import javax.servlet.http.HttpServletRequest;
6 8  
7 9 import org.jeecg.common.exception.JeecgBootException;
8 10 import org.jeecg.common.util.oConvertUtils;
  11 +import org.jeecg.modules.wms.framework.aspectj.dto.ApiAuthentication;
  12 +import org.jeecg.modules.wms.framework.aspectj.dto.RSA256Key;
  13 +import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.core.env.Environment;
9 15  
10 16 import com.auth0.jwt.JWT;
  17 +import com.auth0.jwt.JWTVerifier;
11 18 import com.auth0.jwt.algorithms.Algorithm;
12 19 import com.auth0.jwt.exceptions.JWTDecodeException;
13 20 import com.auth0.jwt.interfaces.DecodedJWT;
14 21  
  22 +import cn.hutool.core.date.DatePattern;
  23 +import cn.hutool.core.date.DateUtil;
  24 +import net.bytebuddy.asm.Advice.This;
  25 +
15 26 public class HuahengJwtUtil {
16 27  
17   - public static final long EXPIRE_TIME = -1;
  28 + /** token失效时间 1天 */
  29 + public static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
  30 +
  31 + public static final String HUAHENG_SYSTEM_ID = "HUAHENG-WMS4-4.0.1";
18 32  
19 33 /**
20 34 * 根据request中的token获取用户账号
... ... @@ -87,6 +101,41 @@ public class HuahengJwtUtil {
87 101 }
88 102  
89 103 /**
  104 + * 生成第三方系统HTTP访问TOKEN
  105 + * @author TanYibin
  106 + * @createDate 2023年2月15日
  107 + * @param apiAuthentication
  108 + * @param algorithm
  109 + * @return
  110 + */
  111 + public static String sign(ApiAuthentication apiAuthentication, Algorithm algorithm) {
  112 + return JWT.create().withClaim("operator", apiAuthentication.getOperator()) // 创建Token 操作人
  113 + .withAudience(apiAuthentication.getAudience()) // Token 使用方
  114 + .withIssuer(apiAuthentication.getIssuer()) // Token 发布者
  115 + .withIssuedAt(DateUtil.date()) // 生成签名时间
  116 + .withExpiresAt(apiAuthentication.getExpireDateTime()) // 过期时间
  117 + .withJWTId(UUID.randomUUID().toString()).sign(algorithm);
  118 + }
  119 +
  120 + /**
  121 + * 生成第三方系统HTTP访问TOKEN
  122 + * @author TanYibin
  123 + * @createDate 2023年2月15日
  124 + * @param apiAuthentication
  125 + * @return
  126 + */
  127 + public static String sign(ApiAuthentication apiAuthentication) {
  128 + RSA256Key rsa256Key = new RSA256Key(); // 获取公钥/私钥
  129 + Algorithm algorithm = Algorithm.RSA256(rsa256Key.getPublicKey(), rsa256Key.getPrivateKey());
  130 + return JWT.create().withClaim("operator", apiAuthentication.getOperator()) // 创建Token 操作人
  131 + .withAudience(apiAuthentication.getAudience()) // Token 使用方
  132 + .withIssuer(apiAuthentication.getIssuer()) // Token 发布者
  133 + .withIssuedAt(DateUtil.date()) // 生成签名时间
  134 + .withExpiresAt(apiAuthentication.getExpireDateTime()) // 过期时间
  135 + .withJWTId(UUID.randomUUID().toString()).sign(algorithm);
  136 + }
  137 +
  138 + /**
90 139 * 获得token中的信息无需secret解密也能获得
91 140 * @return token中包含的用户名
92 141 */
... ... @@ -98,4 +147,35 @@ public class HuahengJwtUtil {
98 147 return null;
99 148 }
100 149 }
  150 +
  151 + /**
  152 + * 生成第三方系统HTTP访问TOKEN
  153 + * @author TanYibin
  154 + * @createDate 2023年2月14日
  155 + * @param args
  156 + * @throws Exception
  157 + */
  158 + public static void main(String[] args) throws Exception {
  159 + ApiAuthentication apiAuthentication = new ApiAuthentication();
  160 + // 生成TOKEN必填参数
  161 + apiAuthentication.setOperator("TanYibin"); // Token提供方
  162 + apiAuthentication.setAudience("ACS001"); // Token使用方
  163 + apiAuthentication.setExpireDateTime(DateUtil.parse("2099-12-31 23:59:59", DatePattern.NORM_DATETIME_PATTERN)); // Token失效时间
  164 +
  165 + String tokenString = sign(apiAuthentication);
  166 + System.out.println("HuahengJwtUtil.sign(apiAuthentication) Token:" + tokenString);
  167 +
  168 + RSA256Key rsa256Key = new RSA256Key(); // 获取公钥/私钥
  169 + Algorithm algorithm = Algorithm.RSA256(rsa256Key.getPublicKey(), rsa256Key.getPrivateKey());
  170 + // Reusable verifier instance 可复用的验证实例
  171 + JWTVerifier verifier = JWT.require(algorithm).withIssuer(HuahengJwtUtil.HUAHENG_SYSTEM_ID).build();
  172 + DecodedJWT jwt = verifier.verify(tokenString);
  173 + System.out.println();
  174 + System.out.println("jwt.getId():" + jwt.getId());
  175 + System.out.println("jwt.getClaim(operator):" + jwt.getClaim("operator").asString());
  176 + System.out.println("jwt.getAudience():" + Arrays.toString(jwt.getAudience().toArray()));
  177 + System.out.println("jwt.getIssuer():" + jwt.getIssuer());
  178 + System.out.println("jwt.getIssuedAt():" + DateUtil.format(jwt.getIssuedAt(), DatePattern.NORM_DATETIME_PATTERN));
  179 + System.out.println("jwt.getExpiresAt():" + DateUtil.format(jwt.getExpiresAt(), DatePattern.NORM_DATETIME_PATTERN));
  180 + }
101 181 }
... ...
huaheng-wms-core/src/main/java/org/jeecg/utils/SecretKeyUtils.java 0 → 100644
  1 +package org.jeecg.utils;
  2 +
  3 +import java.security.Key;
  4 +import java.security.KeyFactory;
  5 +import java.security.KeyPair;
  6 +import java.security.KeyPairGenerator;
  7 +import java.security.PrivateKey;
  8 +import java.security.PublicKey;
  9 +import java.security.interfaces.RSAPrivateKey;
  10 +import java.security.interfaces.RSAPublicKey;
  11 +import java.security.spec.PKCS8EncodedKeySpec;
  12 +import java.security.spec.X509EncodedKeySpec;
  13 +import java.util.Base64;
  14 +import java.util.HashMap;
  15 +import java.util.Map;
  16 +
  17 +import org.jeecg.modules.wms.framework.aspectj.dto.RSA256Key;
  18 +
  19 +import sun.misc.BASE64Decoder;
  20 +import sun.misc.BASE64Encoder;
  21 +
  22 +/**
  23 + * KeyPairGenerator https://www.jianshu.com/p/4de1ee0e7206 key的生成使用方法
  24 + */
  25 +@SuppressWarnings("restriction")
  26 +public class SecretKeyUtils {
  27 +
  28 + public static final String KEY_ALGORITHM = "RSA";
  29 + private static final String PUBLIC_KEY = "RSAPublicKey";
  30 + private static final String PRIVATE_KEY = "RSAPrivateKey";
  31 +
  32 + private static RSA256Key rsa256Key;
  33 +
  34 + // 获得公钥
  35 + public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
  36 + // 获得map中的公钥对象 转为key对象
  37 + Key key = (Key)keyMap.get(PUBLIC_KEY);
  38 + // byte[] publicKey = key.getEncoded();
  39 + // 编码返回字符串
  40 + return encryptBASE64(key.getEncoded());
  41 + }
  42 +
  43 + public static String getPublicKey(RSA256Key rsa256Key) throws Exception {
  44 + // 获得map中的公钥对象 转为key对象
  45 + Key key = rsa256Key.getPublicKey();
  46 + // byte[] publicKey = key.getEncoded();
  47 + // 编码返回字符串
  48 + return encryptBASE64(key.getEncoded());
  49 + }
  50 +
  51 + // 获得私钥
  52 + public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
  53 + // 获得map中的私钥对象 转为key对象
  54 + Key key = (Key)keyMap.get(PRIVATE_KEY);
  55 + // byte[] privateKey = key.getEncoded();
  56 + // 编码返回字符串
  57 + return encryptBASE64(key.getEncoded());
  58 + }
  59 +
  60 + // 获得私钥
  61 + public static String getPrivateKey(RSA256Key rsa256Key) throws Exception {
  62 + // 获得map中的私钥对象 转为key对象
  63 + Key key = rsa256Key.getPrivateKey();
  64 + // byte[] privateKey = key.getEncoded();
  65 + // 编码返回字符串
  66 + return encryptBASE64(key.getEncoded());
  67 + }
  68 +
  69 + // 解码返回byte
  70 + public static byte[] decryptBASE64(String key) throws Exception {
  71 + return (new BASE64Decoder()).decodeBuffer(key);
  72 + }
  73 +
  74 + // 编码返回字符串
  75 + public static String encryptBASE64(byte[] key) throws Exception {
  76 + return (new BASE64Encoder()).encodeBuffer(key);
  77 + }
  78 +
  79 + // 使用KeyPairGenerator 生成公私钥,存放于map对象中
  80 + public static Map<String, Object> initKey() throws Exception {
  81 + /* RSA算法要求有一个可信任的随机数源 */
  82 + // 获得对象 KeyPairGenerator 参数 RSA 1024个字节
  83 + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  84 + keyPairGen.initialize(1024);
  85 +
  86 + // 通过对象 KeyPairGenerator 生成密匙对 KeyPair
  87 + KeyPair keyPair = keyPairGen.generateKeyPair();
  88 +
  89 + // 通过对象 KeyPair 获取RSA公私钥对象RSAPublicKey RSAPrivateKey
  90 + RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
  91 + RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
  92 +
  93 + // 公私钥对象存入map中
  94 + Map<String, Object> keyMap = new HashMap<String, Object>(2);
  95 + keyMap.put(PUBLIC_KEY, publicKey);
  96 + keyMap.put(PRIVATE_KEY, privateKey);
  97 + return keyMap;
  98 + }
  99 +
  100 + /**
  101 + * 获取公私钥
  102 + * @return
  103 + * @throws Exception
  104 + */
  105 + public static synchronized RSA256Key getRSA256Key() throws Exception {
  106 + if (rsa256Key == null) {
  107 + synchronized (RSA256Key.class) {
  108 + if (rsa256Key == null) {
  109 + rsa256Key = new RSA256Key();
  110 + Map<String, Object> map = initKey();
  111 + rsa256Key.setPrivateKey((RSAPrivateKey)map.get(SecretKeyUtils.PRIVATE_KEY));
  112 + rsa256Key.setPublicKey((RSAPublicKey)map.get(SecretKeyUtils.PUBLIC_KEY));
  113 + }
  114 + }
  115 + }
  116 + return rsa256Key;
  117 + }
  118 +
  119 + /**
  120 + * 解码 PublicKey
  121 + * @param key
  122 + * @return
  123 + */
  124 + public static PublicKey getPublicKey(String key) {
  125 + try {
  126 + byte[] byteKey = Base64.getDecoder().decode(key);
  127 + X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
  128 + KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  129 + return keyFactory.generatePublic(x509EncodedKeySpec);
  130 +
  131 + } catch (Exception e) {
  132 + e.printStackTrace();
  133 + }
  134 + return null;
  135 + }
  136 +
  137 + /**
  138 + * 解码 PrivateKey
  139 + * @param key
  140 + * @return
  141 + */
  142 + public static PrivateKey getPrivateKey(String key) {
  143 + try {
  144 + byte[] byteKey = Base64.getDecoder().decode(key);
  145 + PKCS8EncodedKeySpec x509EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
  146 + KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  147 + return keyFactory.generatePrivate(x509EncodedKeySpec);
  148 +
  149 + } catch (Exception e) {
  150 + e.printStackTrace();
  151 + }
  152 + return null;
  153 + }
  154 +
  155 + public static void main(String[] args) {
  156 + Map<String, Object> keyMap;
  157 + try {
  158 + keyMap = initKey(); // 使用 java.security.KeyPairGenerator 生成 公/私钥
  159 + String publicKey = getPublicKey(keyMap);
  160 + System.out.println("公钥:\n" + publicKey);
  161 + String privateKey = getPrivateKey(keyMap);
  162 + System.out.println("私钥:\n" + privateKey);
  163 + } catch (Exception e) {
  164 + e.printStackTrace();
  165 + }
  166 + }
  167 +}
0 168 \ No newline at end of file
... ...
huaheng-wms-core/src/main/resources/application.yml
... ... @@ -3,3 +3,7 @@ spring:
3 3 name: huaheng-wms-core
4 4 profiles:
5 5 active: test
  6 +
  7 +huaheng:
  8 + system:
  9 + Id: HUAHENG-WMS4-4.0.1
... ...