feat:add unauth api
This commit is contained in:
parent
37a1ed6310
commit
64092f405f
@ -48,6 +48,11 @@
|
|||||||
<artifactId>fastjson2</artifactId>
|
<artifactId>fastjson2</artifactId>
|
||||||
<version>2.0.52</version>
|
<version>2.0.52</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -59,6 +64,7 @@
|
|||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.ensign.ensigngateway.conf;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
|
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: TODO
|
||||||
|
* @Date: 2024/10/30 9:30
|
||||||
|
* @Created: by ZZSLL
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CorsResponseHeaderFilter.class);
|
||||||
|
|
||||||
|
private static final String ANY = "*";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
// 指定此过滤器位于NettyWriteResponseFilter之后
|
||||||
|
// 即待处理完响应体后接着处理响应头
|
||||||
|
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
|
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
|
||||||
|
exchange.getResponse().getHeaders().entrySet().stream()
|
||||||
|
.filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
|
||||||
|
.filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||||
|
|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
|
||||||
|
|| kv.getKey().equals(HttpHeaders.VARY)))
|
||||||
|
.forEach(kv ->
|
||||||
|
{
|
||||||
|
// Vary只需要去重即可
|
||||||
|
if(kv.getKey().equals(HttpHeaders.VARY))
|
||||||
|
kv.setValue(kv.getValue().stream().distinct().collect(Collectors.toList()));
|
||||||
|
else{
|
||||||
|
List<String> value = new ArrayList<>();
|
||||||
|
if(kv.getValue().contains(ANY)){ //如果包含*,则取*
|
||||||
|
value.add(ANY);
|
||||||
|
kv.setValue(value);
|
||||||
|
}else{
|
||||||
|
value.add(kv.getValue().get(0)); // 否则默认取第一个
|
||||||
|
kv.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.ensign.ensigngateway.conf;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
import org.springframework.web.cors.reactive.CorsWebFilter;
|
||||||
|
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: TODO
|
||||||
|
* @Date: 2024/10/30 9:21
|
||||||
|
* @Created: by ZZSLL
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class GlobalCorsConfig {
|
||||||
|
@Bean
|
||||||
|
public CorsWebFilter corsWebFilter() {
|
||||||
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
// 这里仅为了说明问题,配置为放行所有域名,生产环境请对此进行修改
|
||||||
|
config.addAllowedOriginPattern("*");
|
||||||
|
// 放行的请求头
|
||||||
|
config.addAllowedHeader("*");
|
||||||
|
// 放行的请求方式,主要有:GET, POST, PUT, DELETE, OPTIONS
|
||||||
|
config.addAllowedMethod("*");
|
||||||
|
// 暴露头部信息
|
||||||
|
config.addExposedHeader("*");
|
||||||
|
// 是否发送cookie
|
||||||
|
config.setAllowCredentials(true);
|
||||||
|
|
||||||
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
|
source.registerCorsConfiguration("/**", config);
|
||||||
|
return new CorsWebFilter(source);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.ensign.ensigngateway.conf;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: TODO
|
||||||
|
* @Date: 2024/10/30 9:34
|
||||||
|
* @Created: by ZZSLL
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
public class GlobalResponseLogFilter implements GlobalFilter, Ordered {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
|
ServerHttpRequest request = exchange.getRequest();
|
||||||
|
// 打印请求路径
|
||||||
|
String path = request.getPath().pathWithinApplication().value();
|
||||||
|
return chain.filter(exchange).then(
|
||||||
|
Mono.fromRunnable(() -> {
|
||||||
|
MultiValueMap<String, String> queryParams = request.getQueryParams();
|
||||||
|
String requestUrl = UriComponentsBuilder.fromPath(path).queryParams(queryParams).build().toUriString();
|
||||||
|
|
||||||
|
// 构建成一条长日志
|
||||||
|
StringBuilder responseLog = new StringBuilder(200);
|
||||||
|
// 日志参数
|
||||||
|
List<Object> responseArgs = new ArrayList<>();
|
||||||
|
responseLog.append("\n\n================ Gateway Response Start ================\n");
|
||||||
|
ServerHttpResponse response = exchange.getResponse();
|
||||||
|
// 状态码个path占位符: 200 get: /xxx/xxx/xxx?a=b
|
||||||
|
responseLog.append("<=== {} {}: {}\n");
|
||||||
|
// 参数
|
||||||
|
String requestMethod = request.getMethod().toString();
|
||||||
|
responseArgs.add(Objects.requireNonNull(response.getStatusCode()).value());
|
||||||
|
responseArgs.add(requestMethod);
|
||||||
|
responseArgs.add(requestUrl);
|
||||||
|
|
||||||
|
// 打印请求头
|
||||||
|
HttpHeaders headers = response.getHeaders();
|
||||||
|
headers.forEach((headerName, headerValue) -> {
|
||||||
|
responseLog.append("===Headers=== {}: {}\n");
|
||||||
|
responseArgs.add(headerName);
|
||||||
|
responseArgs.add(String.join(StringUtils.join(headerValue.toArray())));
|
||||||
|
});
|
||||||
|
|
||||||
|
responseLog.append("================ Gateway Response End =================\n");
|
||||||
|
// 打印执行时间
|
||||||
|
log.info(responseLog.toString(), responseArgs.toArray());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Ordered.HIGHEST_PRECEDENCE;
|
||||||
|
}
|
||||||
|
}
|
@ -7,14 +7,12 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import org.springframework.http.HttpStatusCode;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: TODO
|
* @Description: TODO
|
||||||
@ -36,10 +34,8 @@ public class ProxyFilter implements GlobalFilter {
|
|||||||
String path = exchange.getRequest().getURI().getPath();
|
String path = exchange.getRequest().getURI().getPath();
|
||||||
log.info("path {}", path);
|
log.info("path {}", path);
|
||||||
|
|
||||||
|
String userId = exchange.getRequest().getHeaders().getFirst("userid");
|
||||||
if (path.startsWith("/ierp/kapi/")) {
|
if (path.startsWith("/ierp/kapi/")) {
|
||||||
String userId = exchange.getRequest().getHeaders().getFirst("userid");
|
|
||||||
|
|
||||||
|
|
||||||
log.info("userId: {}", userId);
|
log.info("userId: {}", userId);
|
||||||
|
|
||||||
return webClient.get()
|
return webClient.get()
|
||||||
@ -48,6 +44,7 @@ public class ProxyFilter implements GlobalFilter {
|
|||||||
.accept(MediaType.APPLICATION_JSON)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.onStatus(HttpStatusCode::is4xxClientError, response -> {
|
.onStatus(HttpStatusCode::is4xxClientError, response -> {
|
||||||
|
log.error(response.statusCode().toString());
|
||||||
return Mono.error(new RuntimeException("Unauthorized"));
|
return Mono.error(new RuntimeException("Unauthorized"));
|
||||||
})
|
})
|
||||||
.bodyToMono(String.class)
|
.bodyToMono(String.class)
|
||||||
@ -59,6 +56,7 @@ public class ProxyFilter implements GlobalFilter {
|
|||||||
String token = respJson.getString("data");
|
String token = respJson.getString("data");
|
||||||
exchange.getRequest().mutate()
|
exchange.getRequest().mutate()
|
||||||
.header("access_token", token)
|
.header("access_token", token)
|
||||||
|
.header("userid", userId)
|
||||||
.build();
|
.build();
|
||||||
log.info("token: {}", token);
|
log.info("token: {}", token);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package com.ensign.ensigngateway.conf;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
|
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: TODO
|
||||||
|
* @Date: 2024/10/30 9:32
|
||||||
|
* @Created: by ZZSLL
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class RequestLogFilter implements GlobalFilter, Ordered {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
|
ServerHttpRequest request = exchange.getRequest();
|
||||||
|
// 打印请求路径
|
||||||
|
String path = request.getPath().pathWithinApplication().value();
|
||||||
|
// 打印请求url
|
||||||
|
String requestUrl = this.getOriginalRequestUrl(exchange);
|
||||||
|
|
||||||
|
// **构建成一条长 日志,避免并发下日志错乱**
|
||||||
|
StringBuilder reqLog = new StringBuilder(200);
|
||||||
|
// 日志参数
|
||||||
|
List<Object> reqArgs = new ArrayList<>();
|
||||||
|
reqLog.append("\n\n================ Gateway Request Start ================\n");
|
||||||
|
// 打印路由添加占位符
|
||||||
|
reqLog.append("===> {}: {}\n");
|
||||||
|
// 参数
|
||||||
|
String requestMethod = request.getMethod().name();
|
||||||
|
reqArgs.add(requestMethod);
|
||||||
|
reqArgs.add(requestUrl);
|
||||||
|
|
||||||
|
// 打印请求头
|
||||||
|
HttpHeaders headers = request.getHeaders();
|
||||||
|
headers.forEach((headerName, headerValue) -> {
|
||||||
|
reqLog.append("===Headers=== {}: {}\n");
|
||||||
|
reqArgs.add(headerName);
|
||||||
|
});
|
||||||
|
|
||||||
|
reqLog.append("================ Gateway Request End =================\n");
|
||||||
|
// 打印执行时间
|
||||||
|
log.info(reqLog.toString(), reqArgs.toArray());
|
||||||
|
return chain.filter(exchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getOriginalRequestUrl(ServerWebExchange exchange) {
|
||||||
|
ServerHttpRequest request = exchange.getRequest();
|
||||||
|
LinkedHashSet<URI> uris = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
|
||||||
|
URI requestUri = uris.stream().findFirst().orElse(request.getURI());
|
||||||
|
MultiValueMap<String, String> queryParams = request.getQueryParams();
|
||||||
|
return UriComponentsBuilder.fromPath(requestUri.getRawPath()).queryParams(queryParams).build().toUriString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Ordered.LOWEST_PRECEDENCE;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,9 @@ spring:
|
|||||||
|
|
||||||
cloud:
|
cloud:
|
||||||
gateway:
|
gateway:
|
||||||
|
# globalcors:
|
||||||
|
# add-to-simple-url-handler-mapping: true
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- id: proxy_route
|
- id: proxy_route
|
||||||
uri: ${kingdee.test-inner-end-point}
|
uri: ${kingdee.test-inner-end-point}
|
||||||
@ -12,6 +15,13 @@ spring:
|
|||||||
filters:
|
filters:
|
||||||
- RewritePath=/crm-api/proxy/do/(?<segment>.*), /${segment}
|
- RewritePath=/crm-api/proxy/do/(?<segment>.*), /${segment}
|
||||||
|
|
||||||
|
- id: system-app-api
|
||||||
|
uri: http://127.0.0.1:38080
|
||||||
|
predicates:
|
||||||
|
- Path=/admin-api/**
|
||||||
|
filters:
|
||||||
|
- RewritePath=/admin-api/(?<segment>.*), /${segment}
|
||||||
|
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 20MB
|
max-file-size: 20MB
|
||||||
@ -24,4 +34,4 @@ kingdee:
|
|||||||
test-inner-end-point: 'http://10.64.112.152:8022'
|
test-inner-end-point: 'http://10.64.112.152:8022'
|
||||||
prod-public-end-point: 'http://122.4.221.130:8022'
|
prod-public-end-point: 'http://122.4.221.130:8022'
|
||||||
prod-inner-end-point: 'http://10.64.111.134:8022'
|
prod-inner-end-point: 'http://10.64.111.134:8022'
|
||||||
local: 'http://127.0.0.1:48080'
|
local: 'http://127.0.0.1:38080'
|
||||||
|
@ -55,4 +55,35 @@ public class ProxyController {
|
|||||||
public void proxyRead(@RequestParam String path, HttpServletResponse response) throws AllKingdeeException, IOException {
|
public void proxyRead(@RequestParam String path, HttpServletResponse response) throws AllKingdeeException, IOException {
|
||||||
proxyService.doGetImage(path, response);
|
proxyService.doGetImage(path, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/unauth/do/**", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||||
|
@Operation(summary = "转发接口")
|
||||||
|
@PermitAll
|
||||||
|
public void proxyUnAuth(HttpServletRequest request, HttpServletResponse response) throws IOException, URISyntaxException {
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
String[] unAuthPath = new String[]{
|
||||||
|
// 市场活动详情
|
||||||
|
"/crm-api/proxy/unauth/do/ierp/kapi/v2/yem/yem_receipt/yem_crm_marketactivity/getMarketactivities",
|
||||||
|
|
||||||
|
// 获取机型
|
||||||
|
"/crm-api/proxy/unauth/do/ierp/kapi/v2/yem/yem_crmbasic/yem_crm_region/CRM_yem_crm_region",
|
||||||
|
|
||||||
|
// 活动登记
|
||||||
|
"/crm-api/proxy/unauth/do/ierp/kapi/v2/yem/yem_receipt/api/MarketQRCodeAdd"
|
||||||
|
};
|
||||||
|
if (isAuthorized(requestURI, unAuthPath)) {
|
||||||
|
proxyService.doProxy(request, response);
|
||||||
|
} else {
|
||||||
|
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAuthorized(String requestURI, String[] unAuthPath) {
|
||||||
|
for (String path : unAuthPath) {
|
||||||
|
if (requestURI.equals(path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,9 @@ public class ProxyService {
|
|||||||
URI uri = new URI(request.getRequestURI());
|
URI uri = new URI(request.getRequestURI());
|
||||||
String path = uri.getPath();
|
String path = uri.getPath();
|
||||||
String query = request.getQueryString();
|
String query = request.getQueryString();
|
||||||
|
if (path.contains("/unauth")) {
|
||||||
|
path = path.replace("/unauth", "");
|
||||||
|
}
|
||||||
String target = initBasePath() + path.replace("/crm-api/proxy/do", "");
|
String target = initBasePath() + path.replace("/crm-api/proxy/do", "");
|
||||||
String accessToken;
|
String accessToken;
|
||||||
try {
|
try {
|
||||||
|
Loading…
Reference in New Issue
Block a user