forked from rongchao/epmet-cloud-rizhao
15 changed files with 342 additions and 8 deletions
@ -0,0 +1,30 @@ |
|||||
|
package com.epmet.auth; |
||||
|
|
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 外部应用认证处理器父类 |
||||
|
*/ |
||||
|
public abstract class ExtAppAuthProcessor { |
||||
|
|
||||
|
private Logger logger = LoggerFactory.getLogger(getClass()); |
||||
|
|
||||
|
private int diffMillins = 1000 * 60 * 5; |
||||
|
|
||||
|
public abstract void auth(String appId, String token, Long ts); |
||||
|
|
||||
|
/** |
||||
|
* 时间戳校验 |
||||
|
* @param timestamp |
||||
|
* @return |
||||
|
*/ |
||||
|
protected boolean validTimeStamp(Long timestamp) { |
||||
|
long now = System.currentTimeMillis(); |
||||
|
if (Math.abs(now - timestamp) > diffMillins) { |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
} |
@ -0,0 +1,88 @@ |
|||||
|
package com.epmet.auth; |
||||
|
|
||||
|
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.commons.tools.utils.Result; |
||||
|
import com.epmet.commons.tools.utils.SpringContextUtils; |
||||
|
import com.epmet.feign.EpmetCommonServiceOpenFeignClient; |
||||
|
import com.epmet.jwt.JwtTokenUtils; |
||||
|
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 JwtTokenUtils jwtTokenUtils; |
||||
|
|
||||
|
@Autowired |
||||
|
private RedisUtils redisUtils; |
||||
|
|
||||
|
@Override |
||||
|
public void auth(String appId, String token, Long ts) { |
||||
|
String secret; |
||||
|
if (StringUtils.isBlank(secret = getTokenFromCache(appId))) { |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), String.format("根据AppId:【%s】没有找到对应的秘钥", appId)); |
||||
|
} |
||||
|
|
||||
|
Claims claim; |
||||
|
try { |
||||
|
claim = jwtTokenUtils.getClaimByToken(token, secret); |
||||
|
} catch (Exception e) { |
||||
|
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e); |
||||
|
logger.error("解析token失败:{}", errorStackTrace); |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "解析token失败"); |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "AccessToken不完整"); |
||||
|
} |
||||
|
|
||||
|
if (!validTimeStamp(timestamp)) { |
||||
|
logger.error("extapp token已经超时,请求被拒绝"); |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "AccessToken已经超时"); |
||||
|
} |
||||
|
|
||||
|
if (!appId.equals(appIdIn)) { |
||||
|
logger.error("AppId不对应,token外部的:{}, token内部解析出来的:{}", appId, appIdIn); |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "AppId不匹配"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 通过APP ID查询对应的秘钥 |
||||
|
* @param appId |
||||
|
* @return |
||||
|
*/ |
||||
|
public String getTokenFromCache(String appId) { |
||||
|
String secret = (String)redisUtils.get(RedisKeys.getExternalAppSecretKey(appId)); |
||||
|
if (StringUtils.isBlank(secret)) { |
||||
|
EpmetCommonServiceOpenFeignClient commonService = SpringContextUtils.getBean(EpmetCommonServiceOpenFeignClient.class); |
||||
|
Result<String> result = commonService.getSecret(appId); |
||||
|
if (!result.success()) { |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), result.getInternalMsg()); |
||||
|
} |
||||
|
secret = result.getData(); |
||||
|
redisUtils.set(RedisKeys.getExternalAppSecretKey(appId), secret); |
||||
|
} |
||||
|
return secret; |
||||
|
} |
||||
|
} |
@ -0,0 +1,74 @@ |
|||||
|
package com.epmet.auth; |
||||
|
|
||||
|
import com.epmet.commons.tools.exception.EpmetErrorCode; |
||||
|
import com.epmet.commons.tools.exception.RenException; |
||||
|
import com.epmet.commons.tools.redis.RedisKeys; |
||||
|
import com.epmet.commons.tools.redis.RedisUtils; |
||||
|
import com.epmet.commons.tools.utils.Md5Util; |
||||
|
import com.epmet.commons.tools.utils.Result; |
||||
|
import com.epmet.commons.tools.utils.SpringContextUtils; |
||||
|
import com.epmet.feign.EpmetCommonServiceOpenFeignClient; |
||||
|
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; |
||||
|
|
||||
|
/** |
||||
|
* md5 认证处理器 |
||||
|
*/ |
||||
|
@Component |
||||
|
public class ExtAppMD5AuthProcessor extends ExtAppAuthProcessor { |
||||
|
|
||||
|
private static Logger logger = LoggerFactory.getLogger(ExtAppMD5AuthProcessor.class); |
||||
|
|
||||
|
//@Autowired
|
||||
|
//private EpmetCommonServiceOpenFeignClient commonServiceOpenFeignClient;
|
||||
|
|
||||
|
@Autowired |
||||
|
private RedisUtils redisUtils; |
||||
|
|
||||
|
@Override |
||||
|
public void auth(String appId, String token, Long ts) { |
||||
|
if (ts == null) { |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "需要传入时间戳参数"); |
||||
|
} |
||||
|
String secret; |
||||
|
if (StringUtils.isBlank(secret = getTokenFromCache(appId))) { |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), String.format("根据AppId:%s没有找到对应的秘钥", appId)); |
||||
|
} |
||||
|
|
||||
|
String localDigest = Md5Util.md5(secret.concat(":") + ts); |
||||
|
if (!localDigest.equals(token)) { |
||||
|
// 调用方生成的摘要跟本地生成的摘要不匹配
|
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "签名不匹配,认证失败"); |
||||
|
} |
||||
|
|
||||
|
if (!validTimeStamp(ts)) { |
||||
|
logger.error("AccessToken已经超时,请求被拒绝"); |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "AccessToken已经超时,请求被拒绝"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 通过APP ID查询对应的秘钥 |
||||
|
* |
||||
|
* @param appId |
||||
|
* @return |
||||
|
*/ |
||||
|
public String getTokenFromCache(String appId) { |
||||
|
String secret = (String) redisUtils.get(RedisKeys.getExternalAppSecretKey(appId)); |
||||
|
if (StringUtils.isBlank(secret)) { |
||||
|
EpmetCommonServiceOpenFeignClient commonService = SpringContextUtils.getBean(EpmetCommonServiceOpenFeignClient.class); |
||||
|
Result<String> result = commonService.getSecret(appId); |
||||
|
if (!result.success()) { |
||||
|
throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), result.getInternalMsg()); |
||||
|
} |
||||
|
|
||||
|
secret = result.getData(); |
||||
|
redisUtils.set(RedisKeys.getExternalAppSecretKey(appId), secret); |
||||
|
} |
||||
|
return secret; |
||||
|
} |
||||
|
|
||||
|
} |
Loading…
Reference in new issue