forked from luyan/epmet-cloud-lingshan
				
			
			
			
				Browse Source
			
			
			
			
				
		# Conflicts: # epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtTokenUtils.javamaster
				 10 changed files with 232 additions and 100 deletions
			
			
		| @ -0,0 +1,8 @@ | |||||
|  | package com.epmet.constant; | ||||
|  | 
 | ||||
|  | public interface ExtAppAuthTypeConstant { | ||||
|  | 
 | ||||
|  |     String JWT = "jwt"; | ||||
|  |     String MD5 = "md5"; | ||||
|  | 
 | ||||
|  | } | ||||
| @ -1,10 +1,9 @@ | |||||
| package com.epmet.service; | package com.epmet.service; | ||||
| 
 | 
 | ||||
| import com.epmet.dto.result.ExternalAppAuthResultDTO; | import com.epmet.dto.result.ExternalAppAuthResultDTO; | ||||
| import com.epmet.dto.result.ExternalAppResultDTO; |  | ||||
| 
 | 
 | ||||
| public interface ExternalAppAuthService { | public interface ExternalAppAuthService { | ||||
| 
 | 
 | ||||
|     ExternalAppAuthResultDTO auth(String appId, String token); |     ExternalAppAuthResultDTO auth(String appId, String token, Long ts, String authType); | ||||
| 
 | 
 | ||||
| } | } | ||||
|  | |||||
| @ -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; | ||||
|  |     } | ||||
|  | 
 | ||||
|  | } | ||||
| @ -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); | ||||
|  |     } | ||||
|  | } | ||||
| @ -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); | ||||
|  |     } | ||||
|  | 
 | ||||
|  | } | ||||
					Loading…
					
					
				
		Reference in new issue