|
@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSON; |
|
|
import com.epmet.auth.ExternalAuthProcessor; |
|
|
import com.epmet.auth.ExternalAuthProcessor; |
|
|
import com.epmet.auth.InternalAuthProcessor; |
|
|
import com.epmet.auth.InternalAuthProcessor; |
|
|
import com.epmet.commons.tools.constant.AppClientConstant; |
|
|
import com.epmet.commons.tools.constant.AppClientConstant; |
|
|
|
|
|
import com.epmet.commons.tools.exception.ExceptionUtils; |
|
|
import com.epmet.commons.tools.exception.RenException; |
|
|
import com.epmet.commons.tools.exception.RenException; |
|
|
import com.epmet.commons.tools.utils.IpUtils; |
|
|
import com.epmet.commons.tools.utils.IpUtils; |
|
|
import com.epmet.commons.tools.utils.Result; |
|
|
import com.epmet.commons.tools.utils.Result; |
|
@ -26,13 +27,13 @@ import org.springframework.http.HttpStatus; |
|
|
import org.springframework.http.MediaType; |
|
|
import org.springframework.http.MediaType; |
|
|
import org.springframework.http.server.reactive.ServerHttpRequest; |
|
|
import org.springframework.http.server.reactive.ServerHttpRequest; |
|
|
import org.springframework.stereotype.Component; |
|
|
import org.springframework.stereotype.Component; |
|
|
|
|
|
import org.springframework.util.MultiValueMap; |
|
|
import org.springframework.web.server.ServerWebExchange; |
|
|
import org.springframework.web.server.ServerWebExchange; |
|
|
import reactor.core.publisher.Flux; |
|
|
import reactor.core.publisher.Flux; |
|
|
import reactor.core.publisher.Mono; |
|
|
import reactor.core.publisher.Mono; |
|
|
|
|
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
import java.nio.charset.StandardCharsets; |
|
|
import java.util.Arrays; |
|
|
import java.util.*; |
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* app接口权限过滤器 |
|
|
* app接口权限过滤器 |
|
@ -43,152 +44,197 @@ import java.util.List; |
|
|
@Component("CpAuth") |
|
|
@Component("CpAuth") |
|
|
public class CpAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CpAuthGatewayFilterFactory.CpAuthConfig> { |
|
|
public class CpAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CpAuthGatewayFilterFactory.CpAuthConfig> { |
|
|
|
|
|
|
|
|
private Logger logger = LoggerFactory.getLogger(getClass()); |
|
|
private Logger logger = LoggerFactory.getLogger(getClass()); |
|
|
|
|
|
|
|
|
@Autowired |
|
|
@Autowired |
|
|
private InternalAuthProcessor internalAuthProcessor; |
|
|
private InternalAuthProcessor internalAuthProcessor; |
|
|
|
|
|
|
|
|
@Autowired |
|
|
@Autowired |
|
|
private ExternalAuthProcessor externalAuthProcessor; |
|
|
private ExternalAuthProcessor externalAuthProcessor; |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public List<String> shortcutFieldOrder() { |
|
|
public List<String> shortcutFieldOrder() { |
|
|
return Arrays.asList("enabled"); |
|
|
return Arrays.asList("enabled"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public CpAuthGatewayFilterFactory() { |
|
|
public CpAuthGatewayFilterFactory() { |
|
|
super(CpAuthConfig.class); |
|
|
super(CpAuthConfig.class); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public GatewayFilter apply(CpAuthConfig config) { |
|
|
public GatewayFilter apply(CpAuthConfig config) { |
|
|
return (exchange, chain) -> { |
|
|
return (exchange, chain) -> { |
|
|
if (!config.isEnabled()) { |
|
|
if (!config.isEnabled()) { |
|
|
return chain.filter(exchange); |
|
|
return chain.filter(exchange); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//添加流水号
|
|
|
//1.添加流水号
|
|
|
ServerHttpRequest request = exchange.getRequest(); |
|
|
ServerHttpRequest request = exchange.getRequest(); |
|
|
List<String> tranSerials = request.getHeaders().get(AppClientConstant.TRANSACTION_SERIAL_KEY); |
|
|
List<String> tranSerials = request.getHeaders().get(AppClientConstant.TRANSACTION_SERIAL_KEY); |
|
|
if (CollectionUtils.isEmpty(tranSerials) || StringUtils.isBlank(tranSerials.get(0))) { |
|
|
if (CollectionUtils.isEmpty(tranSerials) || StringUtils.isBlank(tranSerials.get(0))) { |
|
|
request.mutate().header(AppClientConstant.TRANSACTION_SERIAL_KEY, new String[]{getTransactionSerial()}); |
|
|
request.mutate().header(AppClientConstant.TRANSACTION_SERIAL_KEY, new String[]{getTransactionSerial()}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
String authType = getAuthType(request); |
|
|
//2.获取请求路径,参数
|
|
|
String requestUri = request.getPath().pathWithinApplication().value(); |
|
|
String requestUri = request.getPath().pathWithinApplication().value(); |
|
|
|
|
|
MultiValueMap<String, String> queryParams = request.getQueryParams(); |
|
|
logger.info("CpAuthGatewayFilterFactory当前requestUri=[" + requestUri + "],CpAuthGatewayFilterFactory拦截成功,客户端Id:{}", IpUtils.getClientIp(request)); |
|
|
String queryParamsStr = convertQueryParams2String(queryParams); |
|
|
try { |
|
|
logger.info("CpAuthGatewayFilterFactory当前requestUri=[" + requestUri.concat(queryParamsStr) + "],CpAuthGatewayFilterFactory拦截成功,客户端Id:{}", IpUtils.getClientIp(request)); |
|
|
switch (authType) { |
|
|
|
|
|
case AuthTypeConstant.AUTH_TYPE_ALL: |
|
|
//3.认证
|
|
|
externalAuthProcessor.auth(exchange, chain); |
|
|
String authType = getAuthType(request); |
|
|
internalAuthProcessor.auth(exchange, chain); |
|
|
logger.info("认证类型为:{}", authType); |
|
|
break; |
|
|
try { |
|
|
case AuthTypeConstant.AUTH_TYPE_EXTERNAL: |
|
|
switch (authType) { |
|
|
externalAuthProcessor.auth(exchange, chain); |
|
|
case AuthTypeConstant.AUTH_TYPE_ALL: |
|
|
break; |
|
|
externalAuthProcessor.auth(exchange, chain); |
|
|
case AuthTypeConstant.AUTH_TYPE_INTERNAL: |
|
|
internalAuthProcessor.auth(exchange, chain); |
|
|
internalAuthProcessor.auth(exchange, chain); |
|
|
break; |
|
|
break; |
|
|
case AuthTypeConstant.AUTH_TYPE_EXTERNAL: |
|
|
} |
|
|
externalAuthProcessor.auth(exchange, chain); |
|
|
} catch (RenException e) { |
|
|
break; |
|
|
return response(exchange, new Result<>().error(e.getCode(), e.getMessage())); |
|
|
case AuthTypeConstant.AUTH_TYPE_INTERNAL: |
|
|
} catch (Exception e) { |
|
|
internalAuthProcessor.auth(exchange, chain); |
|
|
return response(exchange, new Result<>().error(e.getMessage())); |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
} catch (RenException e) { |
|
|
return chain.filter(exchange); |
|
|
logger.error("CpAuthGatewayFilterFactory认证出错,错误信息:{}", ExceptionUtils.getErrorStackTrace(e)); |
|
|
}; |
|
|
return response(exchange, new Result<>().error(e.getCode(), e.getMessage())); |
|
|
} |
|
|
} catch (Exception e) { |
|
|
|
|
|
logger.error("CpAuthGatewayFilterFactory认证出错,错误信息:{}", ExceptionUtils.getErrorStackTrace(e)); |
|
|
/** |
|
|
return response(exchange, new Result<>().error(e.getMessage())); |
|
|
* 判断需要执行的认证方式(内部应用认证还是外部应用认证) |
|
|
} |
|
|
* @return |
|
|
|
|
|
*/ |
|
|
return chain.filter(exchange); |
|
|
private String getAuthType(ServerHttpRequest request) { |
|
|
}; |
|
|
//String requestUri = request.getPath().pathWithinApplication().value();
|
|
|
} |
|
|
|
|
|
|
|
|
// 是否在外部认证列表中(外部认证列表中的url,是对外部应用开放的,只有在这个列表中的url才对外部应用开放)
|
|
|
/** |
|
|
//boolean inExtAuthPaths = false;
|
|
|
* @return |
|
|
//
|
|
|
* @Description 将url参数转化为String |
|
|
//for (String url : cpProperty.getExternalAuthUrls()) {
|
|
|
* @author wxz |
|
|
// if (antPathMatcher.match(url, requestUri)) {
|
|
|
* @date 2021.08.11 23:12 |
|
|
// inExtAuthPaths = true;
|
|
|
*/ |
|
|
// }
|
|
|
private String convertQueryParams2String(MultiValueMap<String, String> queryParams) { |
|
|
//}
|
|
|
try { |
|
|
|
|
|
if (queryParams == null || queryParams.size() == 0) { |
|
|
String authType = ServerHttpRequestUtils.getRequestParam(request, RequestParamKeys.AUTH_TYPE); |
|
|
return ""; |
|
|
if (StringUtils.isNotBlank(authType) && AuthTypes.TAKE_TOKEN.equals(authType)) { |
|
|
} |
|
|
return AuthTypeConstant.AUTH_TYPE_EXTERNAL; |
|
|
StringBuilder sb = new StringBuilder(""); |
|
|
} |
|
|
queryParams.entrySet().forEach(entry -> { |
|
|
|
|
|
String key = entry.getKey(); |
|
|
boolean needExternal = StringUtils.isNotBlank(request.getHeaders().getFirst(TokenHeaderKeyConstant.ACCESS_TOKEN_HEADER_KEY)); |
|
|
List<String> values = entry.getValue(); |
|
|
boolean needInternal = StringUtils.isNotBlank(request.getHeaders().getFirst(TokenHeaderKeyConstant.AUTHORIZATION_TOKEN_HEADER_KEY)); |
|
|
|
|
|
|
|
|
String value = ""; |
|
|
if (needExternal && needInternal) { |
|
|
if (values != null && values.size() > 0) { |
|
|
return AuthTypeConstant.AUTH_TYPE_ALL; |
|
|
value = values.get(0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (needExternal) { |
|
|
sb.append("&").append(key).append("=").append(value); |
|
|
// url对外部应用开放,并且头里面有AccessToken,那么走外部应用认证
|
|
|
}); |
|
|
return AuthTypeConstant.AUTH_TYPE_EXTERNAL; |
|
|
String result = sb.toString(); |
|
|
} |
|
|
if (result.startsWith("&")) { |
|
|
|
|
|
result = result.substring(1); |
|
|
return AuthTypeConstant.AUTH_TYPE_INTERNAL; |
|
|
return "?".concat(result); |
|
|
} |
|
|
} |
|
|
|
|
|
return ""; |
|
|
/** |
|
|
} catch (Exception e) { |
|
|
* 获取请求头 |
|
|
logger.warn("gateway中将url参数转化为String失败,程序继续执行,错误信息:".concat(ExceptionUtils.getErrorStackTrace(e))); |
|
|
* @param request |
|
|
return ""; |
|
|
* @return |
|
|
} |
|
|
*/ |
|
|
} |
|
|
private String getHeader(ServerHttpRequest request, String headerName) { |
|
|
|
|
|
HttpHeaders headers = request.getHeaders(); |
|
|
/** |
|
|
return headers.getFirst(headerName); |
|
|
* 判断需要执行的认证方式(内部应用认证还是外部应用认证) |
|
|
} |
|
|
* |
|
|
|
|
|
* @return |
|
|
/** |
|
|
*/ |
|
|
* 获取事务流水号 |
|
|
private String getAuthType(ServerHttpRequest request) { |
|
|
* @return |
|
|
//String requestUri = request.getPath().pathWithinApplication().value();
|
|
|
*/ |
|
|
|
|
|
public static String getTransactionSerial() { |
|
|
// 是否在外部认证列表中(外部认证列表中的url,是对外部应用开放的,只有在这个列表中的url才对外部应用开放)
|
|
|
String[] letterPool = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n" |
|
|
//boolean inExtAuthPaths = false;
|
|
|
, "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}; |
|
|
//
|
|
|
|
|
|
//for (String url : cpProperty.getExternalAuthUrls()) {
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
// if (antPathMatcher.match(url, requestUri)) {
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
// inExtAuthPaths = true;
|
|
|
sb.append(letterPool[(int) (Math.random() * 25)]); |
|
|
// }
|
|
|
} |
|
|
//}
|
|
|
|
|
|
|
|
|
sb.append(System.currentTimeMillis()); |
|
|
String authType = ServerHttpRequestUtils.getRequestParam(request, RequestParamKeys.AUTH_TYPE); |
|
|
return sb.toString(); |
|
|
if (StringUtils.isNotBlank(authType) && AuthTypes.TAKE_TOKEN.equals(authType)) { |
|
|
} |
|
|
return AuthTypeConstant.AUTH_TYPE_EXTERNAL; |
|
|
|
|
|
} |
|
|
public static class CpAuthConfig { |
|
|
|
|
|
|
|
|
boolean needExternal = StringUtils.isNotBlank(request.getHeaders().getFirst(TokenHeaderKeyConstant.ACCESS_TOKEN_HEADER_KEY)); |
|
|
/** |
|
|
boolean needInternal = StringUtils.isNotBlank(request.getHeaders().getFirst(TokenHeaderKeyConstant.AUTHORIZATION_TOKEN_HEADER_KEY)); |
|
|
* 控制是否开启认证 |
|
|
|
|
|
*/ |
|
|
if (needExternal && needInternal) { |
|
|
private boolean enabled; |
|
|
return AuthTypeConstant.AUTH_TYPE_ALL; |
|
|
|
|
|
} |
|
|
public CpAuthConfig() { |
|
|
|
|
|
} |
|
|
if (needExternal) { |
|
|
|
|
|
// url对外部应用开放,并且头里面有AccessToken,那么走外部应用认证
|
|
|
public boolean isEnabled() { |
|
|
return AuthTypeConstant.AUTH_TYPE_EXTERNAL; |
|
|
return enabled; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return AuthTypeConstant.AUTH_TYPE_INTERNAL; |
|
|
public void setEnabled(boolean enabled) { |
|
|
} |
|
|
this.enabled = enabled; |
|
|
|
|
|
} |
|
|
/** |
|
|
} |
|
|
* 获取请求头 |
|
|
|
|
|
* |
|
|
protected Mono<Void> response(ServerWebExchange exchange, Object object) { |
|
|
* @param request |
|
|
String json = JSON.toJSONString(object); |
|
|
* @return |
|
|
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8)); |
|
|
*/ |
|
|
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8); |
|
|
private String getHeader(ServerHttpRequest request, String headerName) { |
|
|
exchange.getResponse().setStatusCode(HttpStatus.OK); |
|
|
HttpHeaders headers = request.getHeaders(); |
|
|
return exchange.getResponse().writeWith(Flux.just(buffer)); |
|
|
return headers.getFirst(headerName); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取事务流水号 |
|
|
|
|
|
* |
|
|
|
|
|
* @return |
|
|
|
|
|
*/ |
|
|
|
|
|
public static String getTransactionSerial() { |
|
|
|
|
|
String[] letterPool = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n" |
|
|
|
|
|
, "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}; |
|
|
|
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
|
|
sb.append(letterPool[(int) (Math.random() * 25)]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sb.append(System.currentTimeMillis()); |
|
|
|
|
|
return sb.toString(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static class CpAuthConfig { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 控制是否开启认证 |
|
|
|
|
|
*/ |
|
|
|
|
|
private boolean enabled; |
|
|
|
|
|
|
|
|
|
|
|
public CpAuthConfig() { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean isEnabled() { |
|
|
|
|
|
return enabled; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setEnabled(boolean enabled) { |
|
|
|
|
|
this.enabled = enabled; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected Mono<Void> response(ServerWebExchange exchange, Object object) { |
|
|
|
|
|
String json = JSON.toJSONString(object); |
|
|
|
|
|
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8)); |
|
|
|
|
|
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8); |
|
|
|
|
|
exchange.getResponse().setStatusCode(HttpStatus.OK); |
|
|
|
|
|
return exchange.getResponse().writeWith(Flux.just(buffer)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|