参数加解密
This commit is contained in:
parent
dd96c4bfe5
commit
4cca38069e
|
|
@ -0,0 +1,39 @@
|
|||
package com.bonus.sgzb.auth.controller;
|
||||
|
||||
import com.bonus.sgzb.common.core.domain.R;
|
||||
import com.bonus.sgzb.common.core.utils.SystemConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author ma_sh
|
||||
* @create 2025/4/24 13:35
|
||||
* 获取配置信息
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RefreshScope
|
||||
public class ConfigController {
|
||||
@Resource
|
||||
private SystemConfig systemConfig;
|
||||
|
||||
@GetMapping("getConfig")
|
||||
public R<Object> getConfig() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("loginConfig", systemConfig.getLoginConfig());
|
||||
map.put("registersConfig", systemConfig.getRegistersConfig());
|
||||
map.put("isAdmin", systemConfig.isAdmin());
|
||||
map.put("webSocketurl", systemConfig.getWebsocketurl());
|
||||
map.put("isAddRootCompany", systemConfig.isAddRootCompany());
|
||||
map.put("requestConfig", systemConfig.getRequestConfig());
|
||||
map.put("passwordConfig", systemConfig.getPasswordConfig());
|
||||
map.put("addAddress", systemConfig.isAddAddress());
|
||||
return R.ok(map);
|
||||
}
|
||||
}
|
||||
|
|
@ -123,6 +123,12 @@
|
|||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.16</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.bonus.sgzb.common.core.utils.encryption;
|
||||
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
import cn.hutool.crypto.digest.SM3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @Author ma_sh
|
||||
* @create 2025/4/24 11:10
|
||||
* @Descr sm3加解密
|
||||
*/
|
||||
public class Sm3Util {
|
||||
|
||||
static SM3 sm3 = SmUtil.sm3WithSalt("2cc0c5f9f1749f1632efa9f63e902323".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
|
||||
public static String encrypt(String data) {
|
||||
return Sm3Util.sm3.digestHex(data);
|
||||
}
|
||||
|
||||
public static String encrypt(InputStream data) {
|
||||
return Sm3Util.sm3.digestHex(data);
|
||||
}
|
||||
|
||||
public static String encrypt(File dataFile) {
|
||||
return Sm3Util.sm3.digestHex(dataFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package com.bonus.sgzb.common.core.utils.encryption;
|
||||
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.crypto.Mode;
|
||||
import cn.hutool.crypto.Padding;
|
||||
import cn.hutool.crypto.symmetric.SM4;
|
||||
|
||||
/**
|
||||
* @Author ma_sh
|
||||
* @create 2025/4/24 11:07
|
||||
* @Descr sm4加解密
|
||||
*/
|
||||
public class Sm4Utils {
|
||||
/**
|
||||
* 必须是16字节
|
||||
*/
|
||||
private static final String KEY = "78d1295afa99449b99d6f83820e6965c";
|
||||
|
||||
private static final String IV = "f555adf6c01d0ab0761e626a2dae34a2";
|
||||
/**
|
||||
* 加密数据,使用固定盐
|
||||
*
|
||||
* @param plainText 明文,待加密的字符串
|
||||
* @return 加密后的密文(包含盐),Hex 编码格式,如果加密异常就返回传入的字符串
|
||||
*/
|
||||
public static String encrypt(String plainText) {
|
||||
try {
|
||||
SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, HexUtil.decodeHex(KEY),HexUtil.decodeHex(IV));
|
||||
// 加密带盐的明文
|
||||
byte[] encryptedData = sm4.encrypt(plainText);
|
||||
// 返回带盐的加密结果(Hex编码)
|
||||
return HexUtil.encodeHexStr(encryptedData);
|
||||
} catch (Exception e) {
|
||||
return plainText; // 发生异常时返回传入字符串
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密数据,使用固定盐
|
||||
*
|
||||
* @param cipherText 密文(包含盐),Hex 编码格式的字符串
|
||||
* @return 解密后的明文字符串,如果解密异常就返回传入的字符串
|
||||
*/
|
||||
public static String decrypt(String cipherText) {
|
||||
try {
|
||||
// 初始化SM4解密工具
|
||||
SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, HexUtil.decodeHex(KEY),HexUtil.decodeHex(IV));
|
||||
// 解密数据
|
||||
byte[] decryptedData = sm4.decrypt(cipherText);
|
||||
return new String(decryptedData);
|
||||
} catch (Exception e) {
|
||||
return cipherText; // 发生异常时返回传入字符串
|
||||
}
|
||||
}
|
||||
|
||||
// 测试方法,演示加密和解密过程
|
||||
public static void main(String[] args) {
|
||||
String plainText = "2ab792d986726b6023b1121da6dfebf2a0d3781530e05517cf7175139da04dfd5a26e3c055dfe6b630162e77095905997a86ac58af4dcba544103a7d487fe67793d4e78917c62d6980d1cbc58b4cc4597f69d992cc0736c08476211fc41053dad41718f29b9bd50df9ba99a5e354fd09f05b0cf32cfba639d22c59f704df055ed261fab5efa9f10fc29ed29b38144789bec6de4e3e864cc7c1d6c117beb1ad9a0876c5184d247cd35c49256fd1803ea67540e3433288808e2b798837c76143f6";
|
||||
System.out.println("原文: " + plainText);
|
||||
|
||||
/*// 加密明文
|
||||
String encryptedText = Sm4Utils.encrypt(plainText);
|
||||
System.out.println("加密后: " + encryptedText);*/
|
||||
|
||||
// 解密密文
|
||||
String decryptedText = Sm4Utils.decrypt(plainText);
|
||||
System.out.println("解密后: " + decryptedText);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
package com.bonus.sgzb.gateway.filter;
|
||||
|
||||
import com.bonus.sgzb.common.core.exception.CaptchaException;
|
||||
import com.bonus.sgzb.common.core.utils.encryption.Sm3Util;
|
||||
import com.bonus.sgzb.common.core.utils.encryption.Sm4Utils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author ma_sh
|
||||
* @create 2025/4/24 11:04
|
||||
* 请求内容存储 处理请求内容 内容放在gatewayContext中
|
||||
* 解决数据流被重复读取无数据的 问题
|
||||
* 对formData 数据进行解密
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RequestCoverFilter implements GlobalFilter, Ordered {
|
||||
|
||||
/**
|
||||
* 数据加密标志
|
||||
*/
|
||||
public static final String ENCRYPT = "encryptRequest";
|
||||
/**
|
||||
* 数据完整性校验标志
|
||||
*/
|
||||
public static final String INTEGRALITY = "checkIntegrity";
|
||||
/**
|
||||
* 完整性校验哈希值
|
||||
*/
|
||||
public static final String HMAC_HEADER_NAME = "Params-Hash";
|
||||
|
||||
/**
|
||||
* 处理Web请求,并(可选地)通过给定的 {@link GatewayFilterChain} 委托给下一个 {@code GatewayFilter}。
|
||||
*
|
||||
* @param exchange 当前服务器交换
|
||||
* @param chain 提供委托给下一个过滤器的方式
|
||||
* @return {@code Mono<Void>} 表示请求处理完成的指示
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
// 如果解密和完整性校验均未启用,则直接通过过滤链
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
MediaType contentType = request.getHeaders().getContentType();
|
||||
if (contentType == null) {
|
||||
log.info("请求头中无Content-Type信息,直接继续过滤链。");
|
||||
return chain.filter(exchange);
|
||||
// return handleUrlParams(exchange, chain);
|
||||
} else if (contentType.isCompatibleWith(MediaType.APPLICATION_JSON)) {
|
||||
return handleBodyRequest(exchange, chain);
|
||||
} else {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return HIGHEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理请求体里的参数
|
||||
*
|
||||
* @param exchange 当前服务器交换
|
||||
* @param chain 提供委托给下一个过滤器的方式
|
||||
* @return {@code Mono<Void>} 表示请求处理完成的指示
|
||||
*/
|
||||
private Mono<Void> handleBodyRequest(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
boolean integrality = "true".equalsIgnoreCase(request.getHeaders().getFirst(INTEGRALITY));
|
||||
boolean encrypt = "true".equalsIgnoreCase(request.getHeaders().getFirst(ENCRYPT));
|
||||
return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
|
||||
byte[] body = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(body);
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
String requestBody = new String(body, StandardCharsets.UTF_8);
|
||||
|
||||
// 去掉多余的引号(如果有)
|
||||
if (requestBody.startsWith("\"") && requestBody.endsWith("\"")) {
|
||||
requestBody = requestBody.substring(1, requestBody.length() - 1);
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(requestBody)) {
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
// 解密请求体
|
||||
if (encrypt) {
|
||||
try {
|
||||
requestBody = Sm4Utils.decrypt(requestBody);
|
||||
} catch (Exception e) {
|
||||
log.error("解密请求体时发生错误: {}", e.getMessage(), e);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
}
|
||||
if (ObjectUtils.isEmpty(requestBody)) {
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
|
||||
// 校验数据完整性
|
||||
/*if (integrality) {
|
||||
String providedHmac = requestBody.split("\\|")[1];
|
||||
integrityVerification(providedHmac, requestBody.split("\\|")[0]);
|
||||
}*/
|
||||
requestBody = requestBody.split("\\|")[0];
|
||||
if (ObjectUtils.isEmpty(requestBody)) {
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
|
||||
// 创建新的请求体
|
||||
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
|
||||
DataBuffer newBody = bufferFactory.wrap(requestBody.getBytes(StandardCharsets.UTF_8));
|
||||
ServerHttpRequest newRequest = createNewRequest(exchange, newBody);
|
||||
|
||||
return chain.filter(exchange.mutate().request(newRequest).build());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建包含新请求体的请求
|
||||
*
|
||||
* @param exchange 当前服务器交换
|
||||
* @param newBody 新的请求体数据缓冲区
|
||||
* @return 新的ServerHttpRequest对象
|
||||
*/
|
||||
private ServerHttpRequest createNewRequest(ServerWebExchange exchange, DataBuffer newBody) {
|
||||
return new ServerHttpRequestDecorator(exchange.getRequest()) {
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return Flux.just(newBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.putAll(exchange.getRequest().getHeaders());
|
||||
headers.remove(HttpHeaders.CONTENT_LENGTH);
|
||||
headers.setContentLength(newBody.readableByteCount());
|
||||
return headers;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理url后拼接的参数
|
||||
*
|
||||
* @param exchange 当前服务器交换
|
||||
* @param chain 提供委托给下一个过滤器的方式
|
||||
* @return {@code Mono<Void>} 表示请求处理完成的指示
|
||||
*/
|
||||
private Mono<Void> handleUrlParams(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
try {
|
||||
ServerWebExchange updatedExchange = updateRequestParam(exchange);
|
||||
if (updatedExchange != null) {
|
||||
return chain.filter(updatedExchange);
|
||||
} else {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理 GET 请求时发生错误: {}", e.getMessage(), e);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新查询参数,解密和验证数据完整性
|
||||
*
|
||||
* @param exchange 当前服务器交换
|
||||
* @return 更新后的ServerWebExchange对象,如果无需更新则返回null
|
||||
*/
|
||||
private ServerWebExchange updateRequestParam(ServerWebExchange exchange) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
boolean integrality = "true".equalsIgnoreCase(request.getHeaders().getFirst(INTEGRALITY));
|
||||
boolean encrypt = "true".equalsIgnoreCase(request.getHeaders().getFirst(ENCRYPT));
|
||||
URI uri = request.getURI();
|
||||
String query = uri.getQuery();
|
||||
|
||||
if (!ObjectUtils.isEmpty(query)) {
|
||||
// 解密查询参数
|
||||
if (encrypt) {
|
||||
try {
|
||||
query = Sm4Utils.decrypt(query);
|
||||
} catch (Exception e) {
|
||||
log.error("解密查询参数时发生错误: {}", e.getMessage(), e);
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
}
|
||||
|
||||
// 校验数据完整性
|
||||
// 校验数据完整性
|
||||
if (integrality) {
|
||||
integrityVerification(query.split("\\|")[1], query.split("\\|")[0]);
|
||||
}
|
||||
|
||||
if (ObjectUtils.isEmpty(query)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 更新查询参数
|
||||
Map<String, List<String>> queryParams = Arrays.stream(query.split("&"))
|
||||
.map(param -> param.split("="))
|
||||
.collect(Collectors.toMap(param -> param[0], param -> Collections.singletonList(param[1])));
|
||||
URI newUri = UriComponentsBuilder.fromUri(uri)
|
||||
.replaceQueryParams(CollectionUtils.toMultiValueMap(queryParams))
|
||||
.build(true)
|
||||
.toUri();
|
||||
|
||||
ServerHttpRequest newRequest = request.mutate().uri(newUri).build();
|
||||
return exchange.mutate().request(newRequest).build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据完整性校验
|
||||
*
|
||||
* @param providedHmac 请求头中的 HMAC 值
|
||||
* @param query 请求参数
|
||||
*/
|
||||
private void integrityVerification(String providedHmac, String query) {
|
||||
if (providedHmac == null) {
|
||||
log.error("请求头中缺少 Params-Hash");
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
String encrypt = Sm3Util.encrypt(query);
|
||||
log.debug("加密后的参数: {}", encrypt);
|
||||
log.debug("请求头中的 Params-Hash: {}", providedHmac);
|
||||
if (!encrypt.equals(providedHmac)) {
|
||||
log.error("参数校验失败");
|
||||
throw new CaptchaException("请求参数不正确");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
package com.bonus.sgzb.gateway.filter;
|
||||
|
||||
import com.bonus.sgzb.common.core.utils.encryption.Sm4Utils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.reactivestreams.Publisher;
|
||||
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.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @Author ma_sh
|
||||
* @create 2025/4/24 11:11
|
||||
* 对返回的 data数据进行加密
|
||||
*/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class ResponseEncryptFilter implements GlobalFilter, Ordered {
|
||||
|
||||
/**
|
||||
* 加密标识
|
||||
*/
|
||||
private static final String ENCRYPT_RESPONSE = "encryptResponse";
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
|
||||
// 检查请求头中是否包含加密标志,并且系统是否启用了加密功能
|
||||
if (shouldEncrypt(headers)) {
|
||||
ServerHttpResponse originalResponse = exchange.getResponse();
|
||||
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
|
||||
// 设置响应头
|
||||
addResponseHeaders(originalResponse, headers);
|
||||
// 创建自定义的响应装饰器,用于处理响应数据
|
||||
ServerHttpResponseDecorator responseDecorator = buildResponse(originalResponse, bufferFactory);
|
||||
// 使用装饰器包装后的响应继续处理链
|
||||
return chain.filter(exchange.mutate().response(responseDecorator).build());
|
||||
}
|
||||
|
||||
// 如果不需要加密,直接继续处理链
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return -5;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要对响应数据进行加密
|
||||
*
|
||||
* @param headers 请求头
|
||||
* @return 如果需要加密返回true,否则返回false
|
||||
*/
|
||||
private boolean shouldEncrypt(HttpHeaders headers) {
|
||||
return Boolean.parseBoolean(headers.getFirst(ENCRYPT_RESPONSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加自定义的响应头
|
||||
*
|
||||
* @param response 原始响应对象
|
||||
* @param requestHeaders 请求头
|
||||
*/
|
||||
private void addResponseHeaders(ServerHttpResponse response, HttpHeaders requestHeaders) {
|
||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
response.getHeaders().add(ENCRYPT_RESPONSE, requestHeaders.getFirst(ENCRYPT_RESPONSE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建自定义的响应装饰器,用于加密响应数据
|
||||
*
|
||||
* @param originalResponse 原始响应对象
|
||||
* @param bufferFactory 数据缓冲区工厂
|
||||
* @return 自定义的响应装饰器
|
||||
*/
|
||||
private ServerHttpResponseDecorator buildResponse(ServerHttpResponse originalResponse, DataBufferFactory bufferFactory) {
|
||||
return new ServerHttpResponseDecorator(originalResponse) {
|
||||
@Override
|
||||
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
||||
// 只处理状态码为200 OK的响应,并且响应体是Flux类型
|
||||
if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
|
||||
Flux<? extends DataBuffer> fluxBody = Flux.from(body);
|
||||
|
||||
// 对响应体进行加密处理
|
||||
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
|
||||
DataBuffer joinedBuffer = joinDataBuffers(dataBuffers);
|
||||
byte[] content = readContent(joinedBuffer);
|
||||
DataBufferUtils.release(joinedBuffer);
|
||||
|
||||
// 将响应数据加密
|
||||
String responseData = new String(content, StandardCharsets.UTF_8);
|
||||
responseData = Sm4Utils.encrypt(responseData);
|
||||
byte[] encryptedContent = responseData.getBytes(StandardCharsets.UTF_8);
|
||||
// 设置加密后的内容长度
|
||||
originalResponse.getHeaders().setContentLength(encryptedContent.length);
|
||||
return bufferFactory.wrap(encryptedContent);
|
||||
}));
|
||||
} else {
|
||||
log.error("Failed to retrieve response body. Status code: {}", getStatusCode());
|
||||
}
|
||||
return super.writeWith(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
|
||||
return writeWith(Flux.from(body).flatMapSequential(p -> p));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 将多个DataBuffer连接成一个DataBuffer
|
||||
*
|
||||
* @param dataBuffers DataBuffer列表
|
||||
* @return 连接后的DataBuffer
|
||||
*/
|
||||
private DataBuffer joinDataBuffers(java.util.List<? extends DataBuffer> dataBuffers) {
|
||||
if (dataBuffers.size() > 1) {
|
||||
return new DefaultDataBufferFactory().join(dataBuffers);
|
||||
} else {
|
||||
return dataBuffers.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从DataBuffer中读取字节数组内容
|
||||
*
|
||||
* @param dataBuffer DataBuffer对象
|
||||
* @return 读取到的字节数组
|
||||
*/
|
||||
private byte[] readContent(DataBuffer dataBuffer) {
|
||||
byte[] content = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(content);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ service.interceptors.request.use(config => {
|
|||
//回参是否加密
|
||||
config.headers['encryptResponse'] = systemConfig.requestConfig.encryptResponse && encryptResponse ? 'true' : 'false'
|
||||
// console.log('🚀 ~ config:', config)
|
||||
|
||||
|
||||
// 是否需要设置 token
|
||||
const isToken = (config.headers || {}).isToken === false
|
||||
// 是否需要防止数据重复提交
|
||||
|
|
|
|||
Loading…
Reference in New Issue