针对前面的网关渠道RSA加密,有些页面和接口需要不过滤;所以做了以下不过滤指定路径相关处理配置:
yml配置文件
agilepay:
gateway:
shouldSkipUrls:
- /gatherpay/
- /gatherpay/passive/callback
- /gatherpay/static/webjars/**
- /gatherpay/resources/webjars/
- /gatherpay/resources/
- /gatherpay/
- /gatherpay/webjars/**
- /gatherpay/
- /gatherpay/swagger-resources
- /gatherpay/v3/api-docs
配置文件:NotAuthUrlProperties
import ;
import ;
import ;
import ;
@Data
@Component
@ConfigurationProperties("")
public class NotAuthUrlProperties {
private LinkedHashSet<String> shouldSkipUrls;
}
全局前置过滤器和后置过滤器中加入for循环判断
@Component
@Slf4j
public class WrapperRequestGlobalFilter implements GlobalFilter, Ordered {//, Ordered
@Autowired
private RsaKeyMapper rsaKeyMapper;
@Resource
private NotAuthUrlProperties notAuthUrlProperties;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = ();
ServerHttpResponse response = ();
String currentUrl = ().getURI().getPath();
//1:不需要认证的url,不过滤放行的url
if (shouldSkip(currentUrl)) {
("==========已跳过url{}=====", currentUrl);
return (exchange);
}
("===========网关请求解密开始==================");
ServerRequest serverRequest = new DefaultServerRequest(exchange);
//获取渠道id
String channelId = ().getHeaders().getFirst("channelId");
if (channelId != null) {
//查看是否存在
RsaKey rsaKeyTable = new LambdaQueryChainWrapper<>(rsaKeyMapper)
.eq(RsaKey::getChannelId, channelId).one();
if (rsaKeyTable != null) {
Mono<String> modifiedBody = ()
.flatMap(body -> {
//加密String转json对象
JSONObject jsonObject = (body);
String data = ("data");//获取加密数据值
//获取渠道对应支付私钥(其他项目传来的是用渠道对应支付公钥加密值)
String privateKeyPay = ();
(privateKeyPay + "私钥-------------");
try {
//私钥解密
String sp = (data, privateKeyPay);
// 解密后的值json字符串
String newBody = sp;
(newBody + "------------解密的值---------------------");
//TODO 获取body内容去干你想做的事
return (newBody);
} catch (Exception e) {
();
//只要有异常就返回方法不允许
(HttpStatus.METHOD_NOT_ALLOWED);
//禁止访问
return ();
}
});
BodyInserter bodyInserter = (modifiedBody, );
HttpHeaders headers = new HttpHeaders();
(().getHeaders());
(HttpHeaders.CONTENT_LENGTH);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return (outputMessage, new BodyInserterContext())
.then((() -> {
ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = ();
HttpHeaders httpHeaders = new HttpHeaders();
(());
if (contentLength > 0) {
(contentLength);
} else {
(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return ();
}
};
return (().request(decorator).build());
}));
} else {
//如果rsaKeyTable==null 也不准访问
return ().setComplete();
}
} else {
();
//禁止访问
return ().setComplete();
}
// }
}
@Override
public int getOrder() {
return 0;
}
/**
* 方法实现说明:不需要过滤的路径
* <p>
* // * @param currentUrl 当前请求路径
*/
private boolean shouldSkip(String currentUrl) {
PathMatcher pathMatcher = new AntPathMatcher();
for (String skipPath : ()) {
if ((skipPath, currentUrl)) {
return true;
}
}
return false;
}
}
import ;
import ;
import ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
@Component
@Slf4j
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered {
@Autowired
private RsaKeyMapper rsaKeyMapper;
@Resource
private NotAuthUrlProperties notAuthUrlProperties;
@Override
public int getOrder() {
// -1 is response write filter, must be called before that
return -1;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String currentUrl = ().getURI().getPath();
//1:不需要认证的url
if (shouldSkip(currentUrl)) {
("=====返回已跳过url{}===", currentUrl);
return (exchange);
}
("===============过滤返回值加密开始=====================");
(().getPath().toString() + "----------------------------------");
ServerHttpResponse originalResponse = ();
DataBufferFactory bufferFactory = ();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return ((dataBuffer -> {
byte[] content = new byte[()];
(content);
//释放掉内存
(dataBuffer);
String s = new String(content, ("UTF-8"));
String channelId = ().getHeaders().getFirst("channelId");
RsaKey rsaKeyTable = new LambdaQueryChainWrapper<>(rsaKeyMapper)
.eq(RsaKey::getChannelId, channelId).one();
//通过渠道id获取对应渠道的公钥
String channelPublicKey = ();
//渠道私钥他们对应渠道自己有留存,不需要传||渠道对应的公私钥和支付项目的公私钥他们渠道那边都可以查到?根据渠道id,所以不需要传给他们,他们自己获取即可,我们传渠道公钥加密后的值就可以,他们那边用对应渠道私钥进行解密
("过滤返回值明文:" + s);
String pubKeyEncrypt = "";
try {
pubKeyEncrypt = (s, channelPublicKey);
} catch (Exception e) {
();
}
("过滤返回值公钥加密:" + pubKeyEncrypt);
//TODO,s就是response的值,想修改、查看就随意而为了
byte[] uppedContent = ();//new String(content, ("UTF-8")).getBytes();
return (uppedContent);
}));
}
return (body);
}
};
return (().response(decoratedResponse).build());
// }
}
/**
* 方法实现说明:不需要过滤的路径
* <p>
* // * @param currentUrl 当前请求路径
*/
private boolean shouldSkip(String currentUrl) {
PathMatcher pathMatcher = new AntPathMatcher();
("===========需要跳过的地址==========:" + ());
for (String skipPath : ()) {
if ((skipPath, currentUrl)) {
return true;
}
}
return false;
}
}
在过滤器中家的编码如下
String currentUrl = ().getURI().getPath();
//1:不需要认证的url,不过滤放行的url
if (shouldSkip(currentUrl)) {
("==========已跳过url{}=====", currentUrl);
return (exchange);
}
/**
* 方法实现说明:不需要过滤的路径
* <p>
* // * @param currentUrl 当前请求路径
*/
private boolean shouldSkip(String currentUrl) {
PathMatcher pathMatcher = new AntPathMatcher();
for (String skipPath : ()) {
if ((skipPath, currentUrl)) {
return true;
}
}
return false;
}
}