请求参数解密
public class DecryptionGlobalFilter implements GlobalFilter, Ordered {
private final IgnoreUrlsConfig ignoreUrlsConfig;
public DecryptionGlobalFilter(IgnoreUrlsConfig ignoreUrlsConfig) {
this.ignoreUrlsConfig = ignoreUrlsConfig;
}
/***
* <p>
*请求参数解密
* </p>
* @author 15382
* @date 2022/6/30 13:35
* @param exchange
* @param chain
* @return reactor.core.publisher.Mono<java.lang.Void>
*/
@SneakyThrows
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
AntPathMatcher pathMatcher = new AntPathMatcher();
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String path = request.getURI().getPath(); // 当前调用方法的url
HttpHeaders headers = request.getHeaders();
log.info("HttpMethod:{},Url:{}", request.getMethod(), request.getURI().getRawPath());
// 跳过白名单验证,检查白名单(配置)最好把不拦截路径放入配置文件,此处通过正则
List<String> ignoreUrls = ignoreUrlsConfig.getUrls();
for (String ignoreUrl : ignoreUrls) {
if (pathMatcher.match(ignoreUrl, path)) {
return chain.filter(exchange);
}
}
// 处理参数
MediaType contentType = headers.getContentType();
long contentLength = headers.getContentLength();
if (contentLength > 0) {
if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)||MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {
return readBody(exchange, chain);
}
}
return chain.filter(exchange);
}
private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {
//重新构造request,参考ModifyRequestBodyGatewayFilterFactory
ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
//重点
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> {
//因为约定了终端传参的格式,所以只考虑json的情况,如果是表单传参,请自行增加
if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || MediaType.APPLICATION_JSON_UTF8.isCompatibleWith(mediaType)||MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)) {
String newBody = null;
String key = exchange.getRequest().getHeaders().getFirst("key");
String newKey = RsaUtil.decryptByPrivateKey(key);
try {
// 解密body 此处调用你自己的解密方法
newBody = AESUtils.AESdecrypt(body, newKey);
} catch (Exception e) {
e.getMessage();
}
return Mono.just(newBody);
}
return Mono.empty();
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
//猜测这个就是之前报400错误的元凶,之前修改了body但是没有重新写content length
headers.remove("Content-Length");
//MyCachedBodyOutputMessage 这个类完全就是CachedBodyOutputMessage,只不过CachedBodyOutputMessage不是公共的
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
ServerHttpRequest decorator = this.decorate(exchange, headers, outputMessage);
return returnMononew(chain, exchange.mutate().request(decorator).build());
}));
}
ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, CachedBodyOutputMessage outputMessage) {
return new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
if (contentLength > 0L) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set("Transfer-Encoding", "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
}
private Mono<Void> returnMononew(GatewayFilterChain chain, ServerWebExchange exchange) {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
}));
}
@Override
public int getOrder() {
return 10;
}
}
返回值统一加密处理
public class EncryptionGlobalFilter implements GlobalFilter, Ordered {
/***
* <p>
* TODO
* </p>
* @author 15382
* @date 2022/7/4 13:51
* @param exchange
* @param chain
* @return reactor.core.publisher.Mono<java.lang.Void>
*/
@Override
@SneakyThrows
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.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 super.writeWith(fluxBody.buffer().map(dataBuffers -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffers);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
// 释放掉内存
DataBufferUtils.release(join);
// 返回值得字符串
String str = new String(content, Charset.forName("UTF-8"));
log.info(str);
// 加密方法
String data = null;
try {
data = AESUtils.AESencrypt(str, "qwertyuiopasdfgh");
} catch (Exception e) {
e.printStackTrace();
}
String newKey = "qwertyuiopasdfgh";
// String newKey = RsaUtil.encryptByPrivateKey("qwertyuiopasdfgh");
originalResponse.getHeaders().setContentLength(data.getBytes().length);
originalResponse.getHeaders().set("Key",newKey);
return bufferFactory.wrap(data.getBytes());
}));
}
// if body is not a flux. never got there.
return super.writeWith(body);
}
};
// replace response with decorator
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
@Override
public int getOrder() {
return -1;
}
}
AES工具类
public class AESUtils {
//--------------AES---------------
private static final String KEY = "qwertyuiopasdfgh"; // 密匙,必须16位
private static final String ENCODING = "UTF-8"; // 编码
private static final String ALGORITHM = "AES"; //算法
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; // 默认的加密算法,ECB模式
/**
* AES加密
* @param data
* @return String
*/
public static String AESencrypt(String data,String key) throws Exception
{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(key.getBytes(),"AES"));
byte[] b = cipher.doFinal(data.getBytes("utf-8"));
//采用base64算法进行转码,避免出现中文乱码
return Base64.encodeBase64String(b);
}
/**
* AES解密
* @param data
* @return String
*/
public static String AESdecrypt(String data,String key) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(), "AES"));
byte[] b = cipher.doFinal(Base64.decodeBase64(data));
//采用base64算法进行转码,避免出现中文乱码
return new String(b);
}
public static void main(String[] args) throws Exception {
System.out.println("key = " + "qwertyuiopasdfgh");
System.out.println("text = " + "{\"code\":200,\"message\":\"操作成功\",\"data\":{\"token\":\"eyJhbGciOiJSUzI1NiIsInR5cCI6");
System.out.println("加密为: "+AESUtils.AESencrypt("6fEfqYehC0Xivlh0AxiOcg==", "QJQFf84OE1Qimfq5"));
System.out.println("解密后: "+AESUtils.AESdecrypt("vWvsbsCpZaCwysmk7yrhCA==", "T8VozM1KGmyA3sjL"));
}
}
Rsa工具类
public class RsaUtil {
private static final String KEY_ALGORITHM = "RSA";
private static final String PK = KeyConstants.publicKey;
private static final String SK = KeyConstants.privateKey;
/**
* 使用RSA公钥加密
*/
public static String encryptByPublicKey(String str) {
return Base64.encodeBase64String(getMaxResultEncrypt(str, getPublicKey(Cipher.ENCRYPT_MODE)));
}
/**
* 使用公钥解密
*/
public static String decryptByPublicKey(String data) {
try {
return new String(getMaxResultDecrypt(data, getPublicKey(Cipher.DECRYPT_MODE)));
}catch (Exception e){
throw new BusinessException(ErrorCodeEnum.PUBLIC_KEY_DECRYPT);
}
}
/**
* 使用RSA私钥解密
*
* @param str 加密字符串
*/
public static String decryptByPrivateKey(String str) {
return new String(getMaxResultDecrypt(str, getPrivateKey(Cipher.DECRYPT_MODE)));
}
/**
* 使用RSA私钥加密
* @param data 加密数据
*/
public static String encryptByPrivateKey(String data) {
try {
return Base64.encodeBase64String(getMaxResultEncrypt(data, getPrivateKey(Cipher.ENCRYPT_MODE)));
} catch (Exception e) {
throw new BusinessException(ErrorCodeEnum.PRIVATE_KEY_ENCRYPT);
}
}
/**
* 当长度过长的时候,需要分割后加密 117个字节
*/
private static byte[] getMaxResultEncrypt(String str, Cipher cipher){
try {
byte[] inputArray = str.getBytes(StandardCharsets.UTF_8.name());
int inputLength = inputArray.length;
// 最大加密字节数,超出最大字节数需要分组加密
int maxEncryptBlock = 117;
// 标识
int offSet = 0;
byte[] resultBytes = {};
byte[] cache;
while (inputLength - offSet > 0) {
if (inputLength - offSet > maxEncryptBlock) {
cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock);
offSet += maxEncryptBlock;
} else {
cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
offSet = inputLength;
}
resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
}
return resultBytes;
}catch (Exception e){
e.printStackTrace();
throw new BusinessException(ErrorCodeEnum.ENCRYPT_FAIL);
}
}
/**
* 当长度过长的时候,需要分割后解密 128个字节
*/
private static byte[] getMaxResultDecrypt(String str, Cipher cipher) {
try {
byte[] inputArray = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8.name()));
int inputLength = inputArray.length;
// 最大解密字节数,超出最大字节数需要分组加密
int maxEncryptBlock = 128;
int offSet = 0;
byte[] resultBytes = {};
byte[] cache;
while (inputLength - offSet > 0) {
if (inputLength - offSet > maxEncryptBlock) {
cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock);
offSet += maxEncryptBlock;
} else {
cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
offSet = inputLength;
}
resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
}
return resultBytes;
}catch (Exception e){
e.printStackTrace();
throw new BusinessException(ErrorCodeEnum.DECRYPT_FAIL);
}
}
/**
* 根据加解密类型处理公钥
*
*/
public static Cipher getPublicKey(int mode) {
try {
String publicKey = formatString(PK);
byte[] decoded = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(mode, key);
return cipher;
} catch (Exception e) {
throw new BusinessException(ErrorCodeEnum.PUBLIC_KEY_ERROR);
}
}
/**
* 根据加解密类型处理私钥
*/
public static Cipher getPrivateKey(int mode) {
try {
//mode 加解密模式 ENCRYPT_MODE = 1 DECRYPT_MODE = 2
String privateKey = formatString(SK);
byte[] decoded = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey key = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(mode, key);
return cipher;
} catch (Exception e) {
throw new BusinessException(ErrorCodeEnum.PRIVATE_KEY_ERROR);
}
}
public static String formatString(String source) {
if (source == null) {
return null;
}
return source.replace("\\r", "").replace("\\n", "").trim().replace(" ","");
}
public static void main(String[] args) throws Exception {
String xxStr = "123456";
//加密
String bytes1 = RsaUtil.encryptByPrivateKey(xxStr);
String bytes2 = RsaUtil.encryptByPublicKey(xxStr);
log.info("公钥加密2:{}",bytes2);
log.info("私钥加密1:{}",bytes1);
//解密
log.info("私钥解密密2:{}",RsaUtil.decryptByPrivateKey(bytes2));
log.info("公钥解密密1:{}",RsaUtil.decryptByPublicKey(bytes1));
}
}