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 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; } }