Browse Source
# Conflicts: # epmet-module/epmet-common-service/common-service-server/src/main/java/com/epmet/utils/externalapp/ExtAppJwtTokenUtils.javadev_shibei_match
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; |
|||
|
|||
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); |
|||
|
|||
} |
|||
|
@ -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