You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

92 lines
3.7 KiB

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;
import org.springframework.web.server.ServerWebExchange;
/**
* 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, ServerWebExchange exchange) {
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不匹配");
}
// 添加客户ID等到请求头
exchange.getRequest().mutate().header("CustomerId", customerId);
}
/**
* 通过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;
}
}