Jelajahi Sumber

feature: 令牌获取修改,令牌内容验签

mazq 1 tahun lalu
induk
melakukan
0d4487d72b

+ 9 - 4
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/AppTokenInfoRespVO.java

@@ -17,9 +17,9 @@ import java.util.Date;
 public class AppTokenInfoRespVO {
 
     /**
-     * 应用标识
+     * 应用令牌ID
      */
-    private String appId;
+    private String appTokenId;
 
     /**
      * 用户令牌创建时间
@@ -34,12 +34,17 @@ public class AppTokenInfoRespVO {
     private Date expireAt;
 
     /**
-     * 应用令牌ID
+     * 应用标识
      */
-    private String appTokenId;
+    private String appId;
 
     /**
      * 用户令牌详细信息
      */
     private UserTokenInfoRespVO userToken;
+
+    /**
+     * 应用令牌签名值
+     */
+    private String sign;
 }

+ 26 - 18
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/UserTokenInfoRespVO.java

@@ -1,7 +1,6 @@
 package com.dragoninfo.dcuc.auth.token.vo;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
 
 import java.util.Date;
@@ -18,14 +17,26 @@ import java.util.Date;
 public class UserTokenInfoRespVO {
 
     /**
-     * 用户标识
+     * 用户令牌id
      */
-    private String pid;
+    private String userTokenId;
 
     /**
-     * 用户名称
+     * 用户令牌创建时间
      */
-    private String name;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    /**
+     * 用户令牌到期时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date expireAt;
+
+    /**
+     * 用户标识
+     */
+    private String pid;
 
     /**
      * 组织机构编码
@@ -33,31 +44,28 @@ public class UserTokenInfoRespVO {
     private String orgCode;
 
     /**
-     * 终端设备标识
+     * 终端 IP 地址
      */
-    @JsonProperty("mId")
-    private String mId;
+    private String ip;
 
     /**
-     * 终端环境类型
+     * 终端设备标识
      */
-    private String env;
+    private String mid;
 
     /**
-     * 用户令牌创建时间
+     * 终端环境类型
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createTime;
+    private String env;
 
     /**
-     * 用户令牌到期时间
+     * 用户名称
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date expireAt;
+    private String name;
 
     /**
-     * 用户令牌
+     * 令牌内容签名
      */
-    private String userTokenId;
+    private String sign;
 
 }

+ 14 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/ZeroTrustAppTokenInfoReqVO.java

@@ -0,0 +1,14 @@
+package com.dragoninfo.dcuc.auth.token.vo;
+
+import lombok.Data;
+
+/**
+ * @author mazq
+ * @date 2023/7/14
+ */
+@Data
+public class ZeroTrustAppTokenInfoReqVO {
+
+    private String appTokenId;
+
+}

+ 15 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/ZeroTrustUserTokenInfoReqVO.java

@@ -0,0 +1,15 @@
+package com.dragoninfo.dcuc.auth.token.vo;
+
+import lombok.Data;
+
+/**
+ * @author mazq
+ * @date 2023/7/14
+ */
+@Data
+public class ZeroTrustUserTokenInfoReqVO {
+    /**
+     * 用户令牌id
+     */
+    String userTokenId;
+}

+ 1 - 1
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/impl/zerotrust/ApiCommonBusiness.java

@@ -72,7 +72,7 @@ public class ApiCommonBusiness implements IApiCommonBusiness {
 
     @Override
     public ZeroTrustMessageRespVO checkSecret(ZeroTrustSignReqVO signReqVO) {
-        Boolean checkCallerSign = zerotrustConfig.getCheckCallerSign();
+        Boolean checkCallerSign = zerotrustConfig.getCheckTokenSign();
         log.info("checkCallerSign:{} ", checkCallerSign);
         if (!checkCallerSign) {
             return ZeroTrustMessageRespVO.messageEnumMessage(ZeroTrustBusinessRespEnum.SUCCESS);

+ 20 - 102
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/impl/zerotrust/AuthTokenBusinessImpl.java

@@ -4,14 +4,12 @@ import com.alibaba.fastjson.JSON;
 import com.dragoninfo.dcuc.app.entity.ApplyInfo;
 import com.dragoninfo.dcuc.app.facade.IApplyInfoFacade;
 import com.dragoninfo.dcuc.auth.api.enums.zerotrust.ZeroTrustBusinessRespEnum;
-import com.dragoninfo.dcuc.auth.api.vo.MessageRespVO;
-import com.dragoninfo.dcuc.auth.api.vo.ResultRespPageVo;
-import com.dragoninfo.dcuc.auth.api.vo.ResultRespVO;
 import com.dragoninfo.dcuc.auth.api.vo.zerotrust.ZeroTrustMessageRespVO;
 import com.dragoninfo.dcuc.auth.audit.dto.TokenOperationDto;
 import com.dragoninfo.dcuc.auth.audit.service.log.QmAuditPushService;
 import com.dragoninfo.dcuc.auth.business.ICacheBusiness;
 import com.dragoninfo.dcuc.auth.business.zerotrust.IAuthTokenBusiness;
+import com.dragoninfo.dcuc.auth.business.zerotrust.ITokenRemoteCallBusiness;
 import com.dragoninfo.dcuc.auth.config.zerotrust.DcucAuthZerotrustConfig;
 import com.dragoninfo.dcuc.auth.sub.entity.AuthUserInfo;
 import com.dragoninfo.dcuc.auth.sub.service.IAuthUserInfoService;
@@ -29,15 +27,12 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 
 /**
  * token业务类
@@ -49,10 +44,6 @@ import java.util.*;
 @Service
 public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
 
-    private RestTemplate restTemplate;
-
-    private DcucAuthZerotrustConfig zerotrustConfig;
-
     private IApplyInfoFacade applyInfoFacade;
 
     private IAuthUserInfoService userInfoService;
@@ -63,7 +54,12 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
 
     private SMFactory smFactory;
 
-    private IAuthTokenBusiness tokenBusiness;
+    private ITokenRemoteCallBusiness tokenRemoteCallBusiness;
+
+    @Autowired
+    public void setTokenRemoteCallBusiness(ITokenRemoteCallBusiness tokenRemoteCallBusiness) {
+        this.tokenRemoteCallBusiness = tokenRemoteCallBusiness;
+    }
 
     @Autowired
     public void setSmFactory(SMFactory smFactory) {
@@ -80,16 +76,6 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
         this.qmAuditPushService = qmAuditPushService;
     }
 
-    @Autowired
-    public void setZerotrustConfig(DcucAuthZerotrustConfig zerotrustConfig) {
-        this.zerotrustConfig = zerotrustConfig;
-    }
-
-    @Autowired
-    public void setRestTemplate(RestTemplate restTemplate) {
-        this.restTemplate = restTemplate;
-    }
-
     @Autowired
     public void setApplyInfoFacade(IApplyInfoFacade applyInfoFacade) {
         this.applyInfoFacade = applyInfoFacade;
@@ -102,23 +88,17 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
 
     @Override
     public UserTokenInfoRespVO getUserTokenInfo(String userTokenId) {
+        // 从缓存获取的都是经过令牌签名校验的
         UserTokenInfoRespVO userToken = cacheBusiness.getUserToken(userTokenId);
         if (null != userToken) {
             return userToken;
         }
 
         // 查询用户令牌
-        String tokenQueryUrl = zerotrustConfig.getUserTokenQueryUrl();
-        Map<String, String> param = new HashMap<>();
-        param.put("userTokenId", userTokenId);
-
-        log.info("getUserTokenInfo url:{}, tokenId:{}", tokenQueryUrl, userTokenId);
-
-        UserTokenInfoRespVO tokenInfo = getTokenInfo(tokenQueryUrl, new ParameterizedTypeReference<ResultRespVO<UserTokenInfoRespVO>>() {
-        }, param);
+        UserTokenInfoRespVO userTokenInfo = tokenRemoteCallBusiness.getUserTokenInfo(userTokenId);
         // 添加缓存
-        cacheBusiness.userTokenActionHandle(tokenInfo, TokenActionEnum.ONLINE.getValue());
-        return tokenInfo;
+        cacheBusiness.userTokenActionHandle(userTokenInfo, TokenActionEnum.ONLINE.getValue());
+        return userTokenInfo;
     }
 
     @Override
@@ -127,18 +107,11 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
         if (null != appToken) {
             return appToken;
         }
-        // 获取应用令牌
-        String tokenQueryUrl = zerotrustConfig.getAppTokenQueryUrl();
-        Map<String, String> param = new HashMap<>();
-        param.put("appTokenId", appTokenId);
-
-        log.info("getAppTokenInfo url:{}, tokenId:{}", tokenQueryUrl, appTokenId);
-
-        AppTokenInfoRespVO tokenInfo = getTokenInfo(tokenQueryUrl, new ParameterizedTypeReference<ResultRespVO<AppTokenInfoRespVO>>() {
-        }, param);
+        // 查询应用令牌
+        AppTokenInfoRespVO appTokenInfo = tokenRemoteCallBusiness.getAppTokenInfo(appTokenId);
         // 添加缓存
-        cacheBusiness.appTokenActionHandle(tokenInfo, TokenActionEnum.ONLINE.getValue());
-        return tokenInfo;
+        cacheBusiness.appTokenActionHandle(appTokenInfo, TokenActionEnum.ONLINE.getValue());
+        return appTokenInfo;
     }
 
     @Override
@@ -232,7 +205,7 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
         String userTokenId = reqVo.getUserTokenId();
         String appTokenId = reqVo.getAppTokenId();
         if (StringUtils.isNotBlank(userTokenId)) {
-            UserTokenInfoRespVO userToken = tokenBusiness.getUserTokenInfo(userTokenId);
+            UserTokenInfoRespVO userToken = getUserTokenInfo(userTokenId);
             if (null != userToken) {
                 respVo.setUserTokenOnline(TokenActionEnum.ONLINE.getLabel());
             } else {
@@ -240,7 +213,7 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
             }
         }
         if (StringUtils.isNotBlank(appTokenId)) {
-            AppTokenInfoRespVO appToken = tokenBusiness.getAppTokenInfo(appTokenId);
+            AppTokenInfoRespVO appToken = getAppTokenInfo(appTokenId);
             if (null != appToken) {
                 respVo.setAppTokenOnline(TokenActionEnum.ONLINE.getLabel());
             } else {
@@ -250,7 +223,6 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
         return respVo;
     }
 
-
     /**
      * 生成令牌通知签名
      *
@@ -269,9 +241,6 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
     }
 
 
-
-
-
     private AuthUserVo getAuthUserVo(String pid) {
         // pid为人员身份证号
         // 查询权限中心用户信息, 填充id字段
@@ -284,55 +253,4 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
         return userVo;
     }
 
-    private TokenUserInfoRespVo getTokenUserByPidRemote(String pid) {
-        if (StringUtils.isBlank(pid)) {
-            return null;
-        }
-        String url = zerotrustConfig.getUserInfoQueryUrl();
-        TokenUserInfoReqVo userReqVo = new TokenUserInfoReqVo();
-        userReqVo.setIdcard(pid);
-        HttpEntity<TokenUserInfoReqVo> entity = new HttpEntity<>(userReqVo);
-
-        log.info("getTokenUserByPid url:{}, pid:{}", url, pid);
-
-        ResponseEntity<ResultRespPageVo<TokenUserInfoRespVo>> response = restTemplate.exchange(url, HttpMethod.POST, entity, new ParameterizedTypeReference<ResultRespPageVo<TokenUserInfoRespVo>>() {
-        });
-        ResultRespPageVo<TokenUserInfoRespVo> respBody = getRespBody(response);
-        if (null == respBody) {
-            return null;
-        }
-        ResultRespPageVo.ResultPageContent<TokenUserInfoRespVo> pageContent = respBody.getResult();
-        if (null == pageContent) {
-            return null;
-        }
-        List<TokenUserInfoRespVo> rows = pageContent.getRows();
-        return CollectionUtils.isEmpty(rows) ? null : rows.get(0);
-
-    }
-
-    private <T> T getTokenInfo(String tokenQueryUrl, ParameterizedTypeReference<ResultRespVO<T>> responseType, Map<String, String> param) {
-        HttpEntity<Object> entity = new HttpEntity<>(param);
-        ResponseEntity<ResultRespVO<T>> response = restTemplate.exchange(tokenQueryUrl, HttpMethod.POST, entity,
-                responseType);
-        ResultRespVO<T> respBody = getRespBody(response);
-        if (null == respBody) {
-            return null;
-        }
-        return respBody.getResult();
-    }
-
-    private <T extends MessageRespVO> T getRespBody(ResponseEntity<T> response) {
-        HttpStatus statusCode = response.getStatusCode();
-        if (!statusCode.is2xxSuccessful()) {
-            log.info("request failed, resp:{}", response);
-            return null;
-        }
-        T body = response.getBody();
-        log.info("response body:{}", JSON.toJSONString(body));
-
-        if (body == null || !body.isRespSuccess()) {
-            return null;
-        }
-        return body;
-    }
 }

+ 300 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/impl/zerotrust/TokenRemoteCallBusinessImpl.java

@@ -0,0 +1,300 @@
+package com.dragoninfo.dcuc.auth.business.impl.zerotrust;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import com.dragoninfo.dcuc.auth.api.enums.zerotrust.ZeroTrustBusinessRespEnum;
+import com.dragoninfo.dcuc.auth.api.vo.ResultRespVO;
+import com.dragoninfo.dcuc.auth.business.zerotrust.ITokenRemoteCallBusiness;
+import com.dragoninfo.dcuc.auth.config.zerotrust.DcucAuthZerotrustConfig;
+import com.dragoninfo.dcuc.auth.token.vo.AppTokenInfoRespVO;
+import com.dragoninfo.dcuc.auth.token.vo.UserTokenInfoRespVO;
+import com.dragoninfo.dcuc.auth.token.vo.ZeroTrustAppTokenInfoReqVO;
+import com.dragoninfo.dcuc.auth.token.vo.ZeroTrustUserTokenInfoReqVO;
+import com.dragoninfo.dcuc.common.utils.LangUtil;
+import com.dragonsoft.duceap.commons.util.json.JsonUtils;
+import com.dragonsoft.smtools.loader.SMFactory;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author huangzqa
+ * @date 2023/6/7
+ */
+@Slf4j
+@Component
+public class TokenRemoteCallBusinessImpl implements ITokenRemoteCallBusiness {
+
+    private RestTemplate restTemplate;
+
+    private ObjectMapper objectMapper;
+
+    private SMFactory smFactory;
+
+    private DcucAuthZerotrustConfig zerotrustConfig;
+
+    @Autowired
+    public void setZerotrustConfig(DcucAuthZerotrustConfig zerotrustConfig) {
+        this.zerotrustConfig = zerotrustConfig;
+    }
+
+    @Autowired
+    public void setSmFactory(SMFactory smFactory) {
+        this.smFactory = smFactory;
+    }
+
+    @Autowired
+    public void setRestTemplate(RestTemplate restTemplate) {
+        this.restTemplate = restTemplate;
+    }
+
+    @Override
+    public UserTokenInfoRespVO getUserTokenInfo(String useTokenId) {
+        Assert.notBlank(useTokenId);
+        String requestName = "获取用户令牌信息";
+
+        ZeroTrustUserTokenInfoReqVO zeroTrustUserTokenInfoReqVO = new ZeroTrustUserTokenInfoReqVO();
+        zeroTrustUserTokenInfoReqVO.setUserTokenId(useTokenId);
+
+        log.info("{} 请求 :{}", requestName, JsonUtils.toJSONString(zeroTrustUserTokenInfoReqVO));
+
+        String reqUrl = zerotrustConfig.getUserTokenQueryUrl();
+        RequestEntity<ZeroTrustUserTokenInfoReqVO> httpEntity = new RequestEntity<>(zeroTrustUserTokenInfoReqVO, HttpMethod.POST, URI.create(reqUrl));
+
+        TypeReference<ResultRespVO<UserTokenInfoRespVO>> parameterizedTypeReference =
+                new TypeReference<ResultRespVO<UserTokenInfoRespVO>>() {
+                };
+
+        ResponseEntity<String> responseEntity = restTemplate.exchange(httpEntity, String.class);
+        log.info("{}返回参数 :{}", requestName, JsonUtils.toJSONString(responseEntity));
+
+        if (responseEntity.getStatusCode().is2xxSuccessful()) {
+            String responseEntityJsonBody = responseEntity.getBody();
+
+            ResultRespVO<UserTokenInfoRespVO> responseEntityBody = null;
+            try {
+                responseEntityBody = objectMapper.readValue(responseEntityJsonBody, parameterizedTypeReference);
+            } catch (JsonProcessingException e) {
+                log.error("解析JSON异常", e);
+            }
+            if (responseEntityBody != null) {
+                if (responseEntityBody.getStatusCode().equalsIgnoreCase(ZeroTrustBusinessRespEnum.SUCCESS.getValue())) {
+
+                    // 校验令牌签名
+                    if (zerotrustConfig.getCheckTokenSign()) {
+                        boolean b = checkUserTokenSign(responseEntityJsonBody);
+                        if (!b) {
+                            return null;
+                        }
+                    }
+
+                    return responseEntityBody.getResult();
+                } else {
+                    log.error("{} statusCode:{} , message:{}", requestName, responseEntityBody.getStatusCode(), responseEntityBody.getMessage());
+                }
+            } else {
+                log.error("{} 返回 isnull:{}", requestName, JsonUtils.toJSONString(responseEntity));
+            }
+
+        } else {
+            log.error("{} 请求 error :{}", requestName, JsonUtils.toJSONString(responseEntity));
+        }
+        return null;
+    }
+
+    @Override
+    public AppTokenInfoRespVO getAppTokenInfo(String appTokenId) {
+        Assert.notBlank(appTokenId);
+        String requestName = "获取应用令牌信息";
+
+        ZeroTrustAppTokenInfoReqVO zeroTrustAppTokenInfoReqVO = new ZeroTrustAppTokenInfoReqVO();
+        zeroTrustAppTokenInfoReqVO.setAppTokenId(appTokenId);
+
+        String reqUrl = zerotrustConfig.getAppTokenQueryUrl();
+        log.info("{} 请求 :{}", requestName, JsonUtils.toJSONString(zeroTrustAppTokenInfoReqVO));
+        RequestEntity<ZeroTrustAppTokenInfoReqVO> httpEntity = new RequestEntity<>(zeroTrustAppTokenInfoReqVO, HttpMethod.POST, URI.create(reqUrl));
+
+        TypeReference<ResultRespVO<AppTokenInfoRespVO>> parameterizedTypeReference =
+                new TypeReference<ResultRespVO<AppTokenInfoRespVO>>() {
+                };
+
+        ResponseEntity<String> responseEntity = restTemplate.exchange(httpEntity, String.class);
+        log.info("{}返回参数 :{}", requestName, JsonUtils.toJSONString(responseEntity));
+
+        if (responseEntity.getStatusCode().is2xxSuccessful()) {
+            String responseEntityJsonBody = responseEntity.getBody();
+
+            ResultRespVO<AppTokenInfoRespVO> responseEntityBody = null;
+            try {
+                responseEntityBody = objectMapper.readValue(responseEntityJsonBody, parameterizedTypeReference);
+            } catch (JsonProcessingException e) {
+                log.error("解析JSON异常", e);
+            }
+            if (responseEntityBody != null) {
+                if (responseEntityBody.getStatusCode().equalsIgnoreCase(ZeroTrustBusinessRespEnum.SUCCESS.getValue())) {
+
+                    // 校验令牌签名
+                    if (zerotrustConfig.getCheckTokenSign()) {
+                        boolean b = checkAppTokenSign(responseEntityJsonBody);
+                        if (!b) {
+                            return null;
+                        }
+                    }
+
+                    return responseEntityBody.getResult();
+                } else {
+                    log.error("{} statusCode:{} , message:{}", requestName, responseEntityBody.getStatusCode(), responseEntityBody.getMessage());
+                }
+            } else {
+                log.error("{} 返回 isnull:{}", requestName, JsonUtils.toJSONString(responseEntity));
+            }
+
+        } else {
+            log.error("{} 请求 error :{}", requestName, JsonUtils.toJSONString(responseEntity));
+        }
+        return null;
+    }
+
+    /**
+     * 校验应用令牌签名
+     *
+     * @param appTokenJson 应用令牌信息
+     * @return 是否成功
+     */
+    @SuppressWarnings("unchecked")
+    @SneakyThrows(JsonProcessingException.class)
+    public boolean checkAppTokenSign(String appTokenJson) {
+
+        TypeReference<LinkedHashMap<String, Object>> objectTypeReference = new TypeReference<LinkedHashMap<String, Object>>() {
+        };
+        LinkedHashMap<String, Object> body = objectMapper.readValue(appTokenJson, objectTypeReference);
+        LinkedHashMap<String, Object> userTokenInfo = (LinkedHashMap<String, Object>) body.getOrDefault("result", Collections.emptyMap());
+        LinkedHashMap<String, Object> userToken = (LinkedHashMap<String, Object>) userTokenInfo.getOrDefault("userToken", Collections.emptyMap());
+        String userTokenString = generalAppTokenCheckUserTokenString(userToken);
+        log.info("生成后的用户令牌信息:{}", userTokenString);
+        userTokenInfo.put("userToken", userTokenString);
+        return checkAppTokenSign(userTokenInfo);
+    }
+
+    /**
+     * 校验用户令牌签名
+     *
+     * @param userTokenJson 用户令牌JSON
+     * @return 状态
+     */
+    @SuppressWarnings("unchecked")
+    @SneakyThrows(JsonProcessingException.class)
+    public boolean checkUserTokenSign(String userTokenJson) {
+
+        TypeReference<LinkedHashMap<String, Object>> objectTypeReference = new TypeReference<LinkedHashMap<String, Object>>() {
+        };
+        LinkedHashMap<String, Object> body = objectMapper.readValue(userTokenJson, objectTypeReference);
+        LinkedHashMap<String, Object> userTokenInfo = (LinkedHashMap<String, Object>) body.getOrDefault("result", Collections.emptyMap());
+        return checkUserTokenSign(userTokenInfo);
+    }
+
+    /**
+     * 生成应用令牌校验签名的用户令牌字符串
+     *
+     * @param userTokenMap 用户令牌信息
+     * @return 用户令牌字符串
+     */
+    protected String generalAppTokenCheckUserTokenString(LinkedHashMap<String, Object> userTokenMap) {
+        if (CollUtil.isEmpty(userTokenMap)) {
+            throw new IllegalArgumentException();
+        }
+        String symbol = StrUtil.COMMA + " ";
+
+        StringBuilder userTokenStringBuilder = new StringBuilder("{");
+
+        for (String key : userTokenMap.keySet()) {
+            userTokenStringBuilder.append(key).append("=");
+            String value = userTokenMap.getOrDefault(key, "").toString();
+            userTokenStringBuilder.append(value).append(symbol);
+        }
+
+        String string = userTokenStringBuilder.toString();
+        String subLastSymbol = LangUtil.subLastSymbol(string, symbol);
+        return subLastSymbol + "}";
+    }
+
+
+    /**
+     * 校验用户令牌签名
+     *
+     * @param useTokenInfoMap 用户令牌信息
+     * @return 签名结果
+     */
+    protected boolean checkUserTokenSign(Map<String, Object> useTokenInfoMap) {
+        String userTokenId = useTokenInfoMap.getOrDefault("userTokenId", "").toString();
+        String createTime = useTokenInfoMap.getOrDefault("createTime", "").toString();
+        String expireAt = useTokenInfoMap.getOrDefault("expireAt", "").toString();
+        String pid = useTokenInfoMap.getOrDefault("pid", "").toString();
+        String orgCode = useTokenInfoMap.getOrDefault("orgCode", "").toString();
+        String ip = useTokenInfoMap.getOrDefault("ip", "").toString();
+        String mid = useTokenInfoMap.getOrDefault("mid", "").toString();
+        String env = useTokenInfoMap.getOrDefault("env", "").toString();
+        String sign = useTokenInfoMap.getOrDefault("sign", "").toString();
+
+        String origin = "userTokenId=" + userTokenId +
+                "&createTime=" + createTime + "&expireAt=" + expireAt + "&pid=" + pid + "&orgCode=" + orgCode
+                + "&ip=" + ip + "&mid=" + mid + "&env=" + env;
+        log.info("用户令牌校验签名签名原文:{}", origin);
+
+        String generalSign = smFactory.getSM3().summary(origin).toString().toLowerCase(Locale.ROOT);
+        log.info("用户令牌校验签名签名后的值:{}", generalSign);
+        log.info("用户令牌校验签名令牌信息中的签名值:{}", sign);
+
+        boolean ignoreCase = generalSign.equalsIgnoreCase(sign);
+        log.info("用户令牌:{} 校验签名签名结果:{}", userTokenId, ignoreCase);
+
+        return ignoreCase;
+    }
+
+    /**
+     * 校验应用令牌签名
+     *
+     * @param apTokenInfoMap 应用令牌信息
+     * @return 签名结果
+     */
+    protected boolean checkAppTokenSign(Map<String, Object> apTokenInfoMap) {
+        String appTokenId = apTokenInfoMap.getOrDefault("appTokenId", "").toString();
+        String createTime = apTokenInfoMap.getOrDefault("createTime", "").toString();
+        String expireAt = apTokenInfoMap.getOrDefault("expireAt", "").toString();
+        String appId = apTokenInfoMap.getOrDefault("appId", "").toString();
+        String userToken = apTokenInfoMap.getOrDefault("userToken", "").toString();
+        String sign = apTokenInfoMap.getOrDefault("sign", "").toString();
+
+        String origin = "appTokenId=" + appTokenId + "&createTime=" + createTime + "&expireAt=" +
+                expireAt + "&appId=" + appId + "&userToken=" + userToken;
+        log.info("应用令牌校验签名签名原文:{}", origin);
+
+        String generalSign = smFactory.getSM3().summary(origin).toString().toLowerCase(Locale.ROOT);
+        log.info("应用令牌校验签名签名后的值:{}", generalSign);
+        log.info("应用令牌校验签名令牌信息中的签名值:{}", sign);
+
+        boolean ignoreCase = generalSign.equalsIgnoreCase(sign);
+        log.info("应用令牌:{} 校验签名签名结果:{}", appTokenId, ignoreCase);
+
+        return ignoreCase;
+    }
+}

+ 31 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/zerotrust/ITokenRemoteCallBusiness.java

@@ -0,0 +1,31 @@
+package com.dragoninfo.dcuc.auth.business.zerotrust;
+
+import com.dragoninfo.dcuc.auth.token.vo.AppTokenInfoRespVO;
+import com.dragoninfo.dcuc.auth.token.vo.UserTokenInfoRespVO;
+
+/**
+ * <p>
+ * 竹云相关
+ * </p>
+ *
+ * @author huangzqa
+ * @date 2023/6/7
+ */
+public interface ITokenRemoteCallBusiness {
+
+    /**
+     * 获取用户令牌信息
+     *
+     * @param useTokenId 用户令牌标识
+     * @return 用户令牌信息
+     */
+    UserTokenInfoRespVO getUserTokenInfo(String useTokenId);
+
+    /**
+     * 获取应用令牌信息
+     *
+     * @param appTokenId 应用令牌标识
+     * @return 应用令牌信息
+     */
+    AppTokenInfoRespVO getAppTokenInfo(String appTokenId);
+}

+ 6 - 1
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/config/zerotrust/DcucAuthZerotrustConfig.java

@@ -47,10 +47,15 @@ public class DcucAuthZerotrustConfig {
     private Integer timeStampCheckSeconds = 30 * 60;
 
     /**
-     * 是否检查调用令牌签名值
+     * 是否检查接口调用签名值
      */
     private Boolean checkCallerSign = true;
 
+    /**
+     * 是否校验令牌内容签名值
+     */
+    private Boolean checkTokenSign = true;
+
     /**
      * 应用权限变更通知地址
      */