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.filter.CpProperty; import com.epmet.openapi.constant.AuthTypes; import com.epmet.openapi.constant.RequestParamKeys; import com.epmet.utils.ServerHttpRequestUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; /** * 外部应用认证 */ @Component public class ExternalAuthProcessor extends AuthProcessor { private Logger logger = LoggerFactory.getLogger(getClass()); // 头s public static final String AUTHORIZATION_TOKEN_HEADER_KEY = "Authorization"; public static final String ACCESS_TOKEN_HEADER_KEY = "AccessToken"; public static final String APP_ID_HEADER_KEY = "appId"; public static final String APP_ID_TIMESTAMP_KEY = "ts"; public static final String APP_ID_CUSTOMER_ID_KEY = "CustomerId"; public static final String APP_ID_AUTY_TYPE_KEY = "AuthType"; /** * 认证方式 */ // 调用方生成jwt public static final String APP_AUTH_TYPE_JWT = "jwt"; // 调用方生成md5 public static final String APP_AUTH_TYPE_MD5 = "md5"; @Autowired private ExtAppJwtAuthProcessor jwtAuthProcessor; @Autowired private ExtAppMD5AuthProcessor md5AuthProcessor; @Autowired private ExtAppFetchTokenAuthProcessor fetchTokenAuthProcessor; private final AntPathMatcher antPathMatcher = new AntPathMatcher(); @Autowired private CpProperty cpProperty; @Override public ServerWebExchange auth(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); // 只有在外部应用urls中的url才会允许外部应用访问,否则不允许访问 String requestUri = request.getPath().pathWithinApplication().value(); boolean inPaths = false; for (String url : cpProperty.getExternalOpenUrls()) { if (antPathMatcher.match(url, requestUri)) { inPaths = true; break; } } if (!inPaths) { throw new RenException(EpmetErrorCode.ERR401.getCode(), "所请求的url并未对外部应用开放"); } // 放行白名单 for (String url : cpProperty.getExternalAuthUrlsWhiteList()) { if (antPathMatcher.match(url, requestUri)) { return exchange; } } HttpHeaders headers = request.getHeaders(); String token = headers.getFirst(ACCESS_TOKEN_HEADER_KEY); String ts = headers.getFirst(APP_ID_TIMESTAMP_KEY); String customerId = headers.getFirst(APP_ID_CUSTOMER_ID_KEY); String authType = getAuthType(headers, request); logger.info("外部应用请求认证拦截Aspect执行,token:{}, ts:{}, customerId:{}, authType:{}", token, ts, customerId, authType); // 没传authType或者传的jwt都用jwtprocessor处理 try { if (StringUtils.isBlank(authType) || APP_AUTH_TYPE_JWT.equals(authType)) { String appId = headers.getFirst(APP_ID_HEADER_KEY); if (StringUtils.isAnyBlank(token, appId)) { throw new RenException(EpmetErrorCode.ERR401.getCode(), "请求头中的AccessToken和AppId不能为空"); } jwtAuthProcessor.auth(appId, token, StringUtils.isNotBlank(ts) ? new Long(ts) : null, exchange); } else if (APP_AUTH_TYPE_MD5.equals(authType)) { String appId = headers.getFirst(APP_ID_HEADER_KEY); if (StringUtils.isAnyBlank(token, appId)) { throw new RenException(EpmetErrorCode.ERR401.getCode(), "请求头中的AccessToken和AppId不能为空"); } md5AuthProcessor.auth(appId, token, StringUtils.isNotBlank(ts) ? new Long(ts) : null, exchange); } else if (AuthTypes.TAKE_TOKEN.equals(authType)) { String appId = ServerHttpRequestUtils.getRequestParam(request, RequestParamKeys.APP_ID); if (StringUtils.isBlank(appId)) { throw new RenException(EpmetErrorCode.OPEN_API_PARAMS_MISSING.getCode(),"缺少参数".concat(RequestParamKeys.APP_ID)); } fetchTokenAuthProcessor.auth(appId, token, StringUtils.isNotBlank(ts) ? new Long(ts) : null, exchange); } else { throw new RenException(EpmetErrorCode.OPER_EXTERNAL_APP_AUTH_ERROR.getCode(), "未知的外部认证类型"); } } catch (RenException e) { //return response(exchange, new Result<>().error(e.getCode(), e.getMsg())); throw new RenException(e.getCode(),e.getInternalMsg()); } catch (Exception e) { logger.error("外部应用请求认证发生未知错误:" + ExceptionUtils.getErrorStackTrace(e)); //return response(exchange, new Result<>().error("外部应用请求认证发生未知错误")); throw new RenException("外部应用请求认证发生未知错误"); } return exchange; } private String getAuthType(HttpHeaders headers, ServerHttpRequest request) { String authType = ServerHttpRequestUtils.getRequestParam(request, RequestParamKeys.AUTH_TYPE); if (StringUtils.isBlank(authType)) { authType = headers.getFirst(APP_ID_AUTY_TYPE_KEY); } return authType; } }