From 0b6ee2a2eec5eb020848d1b746e324a338202370 Mon Sep 17 00:00:00 2001 From: wxz Date: Wed, 2 Sep 2020 15:12:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9Amd5=E6=91=98?= =?UTF-8?q?=E8=A6=81=E9=AA=8C=E7=AD=BE=E6=96=B9=E5=BC=8F=E7=9A=84=E5=A4=96?= =?UTF-8?q?=E9=83=A8=E5=BA=94=E7=94=A8=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aspect/ExternalAppRequestAuthAspect.java | 13 ++- .../dto/form/ExternalAppAuthFormDTO.java | 10 ++ .../constant/ExtAppAuthTypeConstant.java | 8 ++ .../controller/ExternalAppController.java | 4 +- .../epmet/service/ExternalAppAuthService.java | 3 +- .../impl/ExternalAppAuthServiceImpl.java | 108 +++--------------- .../externalapp/ExtAppAuthProcessor.java | 73 ++++++++++++ .../externalapp/ExtAppJwtAuthProcessor.java | 61 ++++++++++ .../externalapp/ExtAppJwtTokenUtils.java | 8 +- .../externalapp/ExtAppMD5AuthProcessor.java | 42 +++++++ 10 files changed, 231 insertions(+), 99 deletions(-) create mode 100644 epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/constant/ExtAppAuthTypeConstant.java create mode 100644 epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppAuthProcessor.java create mode 100644 epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtAuthProcessor.java create mode 100644 epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppMD5AuthProcessor.java diff --git a/epmet-commons/epmet-commons-extapp-auth/src/main/java/com/epmet/commons/extappauth/aspect/ExternalAppRequestAuthAspect.java b/epmet-commons/epmet-commons-extapp-auth/src/main/java/com/epmet/commons/extappauth/aspect/ExternalAppRequestAuthAspect.java index b4cfd11c27..82ffd68882 100644 --- a/epmet-commons/epmet-commons-extapp-auth/src/main/java/com/epmet/commons/extappauth/aspect/ExternalAppRequestAuthAspect.java +++ b/epmet-commons/epmet-commons-extapp-auth/src/main/java/com/epmet/commons/extappauth/aspect/ExternalAppRequestAuthAspect.java @@ -37,6 +37,9 @@ public class ExternalAppRequestAuthAspect { public static final String ACCESS_TOKEN_HEADER_KEY = "AccessToken"; public static final String APP_ID_HEADER_KEY = "appId"; + public static final String APP_ID_TIMESTAMP_KEY = "ts"; + public static final String APP_ID_CUSTOMER_ID_KEY = "CustomerId"; + public static final String APP_ID_AUTY_TYPE_KEY = "AuthType"; @Autowired private EpmetCommonServiceOpenFeignClient commonServiceOpenFeignClient; @@ -52,6 +55,9 @@ public class ExternalAppRequestAuthAspect { HttpServletRequest request = getRequest(); String token = request.getHeader(ACCESS_TOKEN_HEADER_KEY); String appId = request.getHeader(APP_ID_HEADER_KEY); + String ts = request.getHeader(APP_ID_TIMESTAMP_KEY); + String customerId = request.getHeader(APP_ID_CUSTOMER_ID_KEY); + String authType = request.getHeader(APP_ID_AUTY_TYPE_KEY); if (StringUtils.isAnyBlank(token, appId)) { throw new RenException("请求头中的token和appId不能为空"); @@ -62,6 +68,11 @@ public class ExternalAppRequestAuthAspect { ExternalAppAuthFormDTO form = new ExternalAppAuthFormDTO(); form.setAppId(appId); form.setToken(token); + form.setAuthType(authType); + if (StringUtils.isNotBlank(ts)) { + // 将字符串转化为时间 + form.setTs(new Long(ts)); + } Result result = commonServiceOpenFeignClient.externalAppAuth(form); if (result == null) { throw new RenException("调用服务进行外部应用认证,返回null"); @@ -84,7 +95,7 @@ public class ExternalAppRequestAuthAspect { if (parameters[i].getType() == ExternalAppRequestParam.class) { ExternalAppRequestParam requestParam = (ExternalAppRequestParam) point.getArgs()[i]; requestParam.setAppId(appId); - requestParam.setCustomerId(authResult.getCustomerId()); + requestParam.setCustomerId(authResult.getCustomerId() == null ? customerId : authResult.getCustomerId()); } } } diff --git a/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/form/ExternalAppAuthFormDTO.java b/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/form/ExternalAppAuthFormDTO.java index 2d6470db80..a144b37f81 100644 --- a/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/form/ExternalAppAuthFormDTO.java +++ b/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/dto/form/ExternalAppAuthFormDTO.java @@ -15,4 +15,14 @@ public class ExternalAppAuthFormDTO { */ private String token; + /** + * 时间戳 + */ + private Long ts; + + /** + * 认证类型:md5,jwt + */ + private String authType; + } diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/constant/ExtAppAuthTypeConstant.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/constant/ExtAppAuthTypeConstant.java new file mode 100644 index 0000000000..b281c6d7e6 --- /dev/null +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/constant/ExtAppAuthTypeConstant.java @@ -0,0 +1,8 @@ +package com.epmet.constant; + +public interface ExtAppAuthTypeConstant { + + String JWT = "jwt"; + String MD5 = "md5"; + +} diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/controller/ExternalAppController.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/controller/ExternalAppController.java index 976c4e4ef0..50e9a7b891 100644 --- a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/controller/ExternalAppController.java +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/controller/ExternalAppController.java @@ -40,12 +40,14 @@ public class ExternalAppController { public Result auth(@RequestBody ExternalAppAuthFormDTO formDTO) { String appId = formDTO.getAppId(); String token = formDTO.getToken(); + Long ts = formDTO.getTs(); + String authType = formDTO.getAuthType(); if (StringUtils.isAnyBlank(token, appId)) { throw new RenException("请求头中的token和appId不能为空"); } logger.info("外部应用请求认证拦截Aspect。appId:{}, token:{}", appId, token); - ExternalAppAuthResultDTO auth = externalAppAuthService.auth(appId, token); + ExternalAppAuthResultDTO auth = externalAppAuthService.auth(appId, token, ts, authType); return new Result().ok(auth); } diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/ExternalAppAuthService.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/ExternalAppAuthService.java index e1158c592c..3f76a1e83d 100644 --- a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/ExternalAppAuthService.java +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/ExternalAppAuthService.java @@ -1,10 +1,9 @@ package com.epmet.service; import com.epmet.dto.result.ExternalAppAuthResultDTO; -import com.epmet.dto.result.ExternalAppResultDTO; public interface ExternalAppAuthService { - ExternalAppAuthResultDTO auth(String appId, String token); + ExternalAppAuthResultDTO auth(String appId, String token, Long ts, String authType); } diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/impl/ExternalAppAuthServiceImpl.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/impl/ExternalAppAuthServiceImpl.java index e87a4c6f46..e598c3ab2c 100644 --- a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/impl/ExternalAppAuthServiceImpl.java +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/service/impl/ExternalAppAuthServiceImpl.java @@ -1,19 +1,10 @@ package com.epmet.service.impl; -import com.epmet.commons.tools.exception.EpmetErrorCode; -import com.epmet.commons.tools.exception.ExceptionUtils; -import com.epmet.commons.tools.exception.RenException; -import com.epmet.commons.tools.redis.RedisKeys; -import com.epmet.commons.tools.redis.RedisUtils; -import com.epmet.dao.ExternalAppDao; -import com.epmet.dao.ExternalAppSecretDao; +import com.epmet.constant.ExtAppAuthTypeConstant; import com.epmet.dto.result.ExternalAppAuthResultDTO; -import com.epmet.dto.result.ExternalAppResultDTO; -import com.epmet.entity.ExternalAppEntity; -import com.epmet.entity.ExternalAppSecretEntity; import com.epmet.service.ExternalAppAuthService; -import com.epmet.utils.externalapp.ExtAppJwtTokenUtils; -import io.jsonwebtoken.Claims; +import com.epmet.utils.externalapp.ExtAppJwtAuthProcessor; +import com.epmet.utils.externalapp.ExtAppMD5AuthProcessor; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,90 +17,23 @@ public class ExternalAppAuthServiceImpl implements ExternalAppAuthService { private static Logger logger = LoggerFactory.getLogger(ExternalAppAuthServiceImpl.class); @Autowired - private RedisUtils redisUtils; + private ExtAppJwtAuthProcessor jwtAuthProcessor; @Autowired - private ExtAppJwtTokenUtils jwtTokenUtils; - - @Autowired - private ExternalAppSecretDao externalAppSecretDao; - - @Autowired - private ExternalAppDao externalAppDao; - - private int diffMillins = 1000 * 60 * 5; + private ExtAppMD5AuthProcessor md5AuthProcessor; @Override - public ExternalAppAuthResultDTO auth(String appId, String token) { - String secret; - if (StringUtils.isBlank(secret = getTokenByAppId(appId))) { - return fillAuthResult(false, String.format("根据AppId:%s没有找到对应的秘钥", appId), null); + public ExternalAppAuthResultDTO auth(String appId, String token, Long ts, String authType) { + // 没传或者传的jwt都用jwtprocessor处理 + if (StringUtils.isBlank(authType) || ExtAppAuthTypeConstant.JWT.equals(authType)) { + return jwtAuthProcessor.auth(appId, token, ts); + } else if (ExtAppAuthTypeConstant.MD5.equals(authType)) { + return md5AuthProcessor.auth(appId, token, ts); + } else { + ExternalAppAuthResultDTO rst = new ExternalAppAuthResultDTO(); + rst.setMessage("错误的认证类型"); + rst.setSuccess(false); + return rst; } - - Claims claim; - try { - claim = jwtTokenUtils.getClaimByToken(token, secret); - } catch (Exception e) { - String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); - logger.error("解析token失败:{}", errorStackTrace); - return fillAuthResult(false, "解析token失败", null); - } - - String appIdIn = (String)claim.get("appId"); - String customerId = (String)claim.get("customerId"); - Long timestamp = (Long)claim.get("ts"); - - //校验时间戳,允许5分钟误差 - if (StringUtils.isAnyBlank(appIdIn, customerId) || timestamp == null) { - logger.error("access token不完整。{},{},{}", appIdIn, customerId, timestamp); - return fillAuthResult(false, "access token不完整。", null); - } - - // TODO -// if (!validTimeStamp(timestamp)) { -// logger.error("服务器存在时差过大,请求被拒绝", appId, appIdIn); -// return fillAuthResult(false, "服务器存在时差过大,请求被拒绝", null); -// } - - if (!appId.equals(appIdIn)) { - logger.error("AppId不对应,token外部的:{}, token内部解析出来的:{}", appId, appIdIn); - return fillAuthResult(false, "Header中的AppId不匹配", null); - } - return fillAuthResult(true, "解析成功", customerId); - } - - private boolean validTimeStamp(Long timestamp) { - long now = System.currentTimeMillis(); -// System.out.println(new Date(timestamp)); - if (Math.abs(now - timestamp) > diffMillins) { - return false; - } - return true; - } - - /** - * 通过APP ID查询对应的秘钥 - * @param appId - * @return - */ - public String getTokenByAppId(String appId) { - String secret = (String)redisUtils.get(RedisKeys.getExternalAppSecretKey(appId)); - if (StringUtils.isBlank(secret)) { - ExternalAppSecretEntity secretEntity = externalAppSecretDao.getSecretsByAppId(appId); - if (secretEntity == null) { - return null; - } - secret = secretEntity.getSecret(); - redisUtils.set(RedisKeys.getExternalAppSecretKey(appId), secret); - } - return secret; - } - - public ExternalAppAuthResultDTO fillAuthResult(Boolean result, String message, String customerId) { - ExternalAppAuthResultDTO authResult = new ExternalAppAuthResultDTO(); - authResult.setSuccess(result); - authResult.setMessage(message); - authResult.setCustomerId(customerId); - return authResult; } } diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppAuthProcessor.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppAuthProcessor.java new file mode 100644 index 0000000000..b0f5fef000 --- /dev/null +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppAuthProcessor.java @@ -0,0 +1,73 @@ +package com.epmet.utils.externalapp; + +import com.epmet.commons.tools.redis.RedisKeys; +import com.epmet.commons.tools.redis.RedisUtils; +import com.epmet.dao.ExternalAppSecretDao; +import com.epmet.dto.result.ExternalAppAuthResultDTO; +import com.epmet.entity.ExternalAppSecretEntity; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; + + +/** + * 外部应用认证处理器父类 + */ +public abstract class ExtAppAuthProcessor { + + @Autowired + private RedisUtils redisUtils; + + @Autowired + private ExternalAppSecretDao externalAppSecretDao; + + private int diffMillins = 1000 * 60 * 5; + + public abstract ExternalAppAuthResultDTO auth(String appId, String token, Long ts); + + /** + * 通过APP ID查询对应的秘钥 + * @param appId + * @return + */ + public String getTokenByAppId(String appId) { + String secret = (String)redisUtils.get(RedisKeys.getExternalAppSecretKey(appId)); + if (StringUtils.isBlank(secret)) { + ExternalAppSecretEntity secretEntity = externalAppSecretDao.getSecretsByAppId(appId); + if (secretEntity == null) { + return null; + } + secret = secretEntity.getSecret(); + redisUtils.set(RedisKeys.getExternalAppSecretKey(appId), secret); + } + return secret; + } + + /** + * 时间戳校验 + * @param timestamp + * @return + */ + protected boolean validTimeStamp(Long timestamp) { + long now = System.currentTimeMillis(); + if (Math.abs(now - timestamp) > diffMillins) { + return false; + } + return true; + } + + /** + * 封装结果 + * @param result + * @param message + * @param customerId + * @return + */ + public ExternalAppAuthResultDTO fillAuthResult(Boolean result, String message, String customerId) { + ExternalAppAuthResultDTO authResult = new ExternalAppAuthResultDTO(); + authResult.setSuccess(result); + authResult.setMessage(message); + authResult.setCustomerId(customerId); + return authResult; + } + +} diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtAuthProcessor.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtAuthProcessor.java new file mode 100644 index 0000000000..2ec771fd02 --- /dev/null +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtAuthProcessor.java @@ -0,0 +1,61 @@ +package com.epmet.utils.externalapp; + +import com.epmet.commons.tools.exception.ExceptionUtils; +import com.epmet.dto.result.ExternalAppAuthResultDTO; +import io.jsonwebtoken.Claims; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * jwt 认证处理器 + */ +@Component +public class ExtAppJwtAuthProcessor extends ExtAppAuthProcessor { + + private static Logger logger = LoggerFactory.getLogger(ExtAppJwtAuthProcessor.class); + + @Autowired + private ExtAppJwtTokenUtils jwtTokenUtils; + + public ExternalAppAuthResultDTO auth(String appId, String token, Long ts) { + String secret; + if (StringUtils.isBlank(secret = getTokenByAppId(appId))) { + return fillAuthResult(false, String.format("根据AppId:%s没有找到对应的秘钥", appId), null); + } + + Claims claim; + try { + claim = jwtTokenUtils.getClaimByToken(token, secret); + } catch (Exception e) { + String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); + logger.error("解析token失败:{}", errorStackTrace); + return fillAuthResult(false, "解析token失败", null); + } + + String appIdIn = (String)claim.get("appId"); + String customerId = (String)claim.get("customerId"); + Long timestamp = (Long)claim.get("ts"); + + //校验时间戳,允许5分钟误差 + if (StringUtils.isAnyBlank(appIdIn, customerId) || timestamp == null) { + logger.error("access token不完整。{},{},{}", appIdIn, customerId, timestamp); + return fillAuthResult(false, "access token不完整。", null); + } + + // TODO 暂时去掉时间差判断 + //if (!validTimeStamp(timestamp)) { + // logger.error("服务器存在时差过大,请求被拒绝"); + // return fillAuthResult(false, "服务器存在时差过大,请求被拒绝", null); + //} + + if (!appId.equals(appIdIn)) { + logger.error("AppId不对应,token外部的:{}, token内部解析出来的:{}", appId, appIdIn); + return fillAuthResult(false, "Header中的AppId不匹配", null); + } + + return fillAuthResult(true, "解析成功,认证成功", customerId); + } +} diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtTokenUtils.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtTokenUtils.java index 1c3a326c75..2e49c80102 100644 --- a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtTokenUtils.java +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtTokenUtils.java @@ -75,11 +75,13 @@ public class ExtAppJwtTokenUtils { public static void genToken() { HashMap claim = new HashMap<>(); - claim.put("appId", "227fb75ae4baa820755aaf43bf7f0a69"); + claim.put("appId", "2c448b7da527055fbeebb628f8d3dcb0"); claim.put("customerId", "c1"); - claim.put("ts", System.currentTimeMillis() - 1000 * 60 * 4); + long ts = System.currentTimeMillis() - 1000 * 60 * 4; + System.out.println("时间戳:" + ts); + claim.put("ts", ts); - String abc = new ExtAppJwtTokenUtils().createToken(claim, "4a762660254c57996343f8ee42fbc0a6"); + String abc = new ExtAppJwtTokenUtils().createToken(claim, "d4b73db4cf8e46ef99fa1f95149c2791ef2396fded114dd09e406cbce83fc88a"); System.out.println(abc); } diff --git a/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppMD5AuthProcessor.java b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppMD5AuthProcessor.java new file mode 100644 index 0000000000..3954738758 --- /dev/null +++ b/epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppMD5AuthProcessor.java @@ -0,0 +1,42 @@ +package com.epmet.utils.externalapp; + +import com.epmet.commons.tools.utils.Md5Util; +import com.epmet.dto.result.ExternalAppAuthResultDTO; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * md5 认证处理器 + */ +@Component +public class ExtAppMD5AuthProcessor extends ExtAppAuthProcessor { + + private static Logger logger = LoggerFactory.getLogger(ExtAppMD5AuthProcessor.class); + + public ExternalAppAuthResultDTO auth(String appId, String token, Long ts) { + if (ts == null) { + return fillAuthResult(false, "需要传入时间戳参数", null); + } + String secret; + if (StringUtils.isBlank(secret = getTokenByAppId(appId))) { + return fillAuthResult(false, String.format("根据AppId:%s没有找到对应的秘钥", appId), null); + } + + String localDigest = Md5Util.md5(secret.concat(":") + ts); + if (!localDigest.equals(token)) { + // 调用方生成的摘要跟本地生成的摘要不匹配 + return fillAuthResult(false, "签名不匹配,认证失败", null); + } + + // TODO 暂时去掉时间差判断 + //if (!validTimeStamp(ts)) { + // logger.error("服务器存在时差过大,请求被拒绝"); + // return fillAuthResult(false, "服务器存在时差过大,请求被拒绝", null); + //} + + return fillAuthResult(true, "签名匹配,认证成功", null); + } + +}