700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > vue java Gateway 使用RSA AES加密算法实现接口交互加密传输

vue java Gateway 使用RSA AES加密算法实现接口交互加密传输

时间:2024-01-01 22:52:34

相关推荐

vue java Gateway 使用RSA AES加密算法实现接口交互加密传输

客户端加密密钥获取流程

服务器端存有一份RSA公钥私钥、一份AES密钥

客户端获取服务器的RSA公钥

客户端生成随机的AES密钥,将生成的密钥通过RSA公钥加密发送给服务器

服务器接收到加密后的密钥后,通过RSA私钥解密获取客户端的密钥

服务器将服务器端AES密钥通过解密获得的AES密钥加密后返还客户端

客户端获取后解密获得服务器端端密钥

思路

前端利用路由前置守卫,访问页面触发前置守卫

前置守卫中判断vuex中是密钥的值是否为空

当为空的时候通过上述流程向后端获取密钥。

在axios拦截器中对需要加密的数据进行加密解密

后端分布式中在网关服务中使用拦截器同意对需要加密的数据进行加密解密

前后端加密算法工具类

前端vue RSA工具类

import { JSEncrypt } from 'jsencrypt'export default {//加密encrypt(word, keyStr) {let encrypt = new JSEncrypt()encrypt.setPublicKey(keyStr) // 公钥return encrypt.encrypt(word);}}

前端vue AES工具类

import CryptoJS from 'crypto-js';export default {//随机生成指定数量的16进制keygeneratekey(num = 16) {let library = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";let key = "";for (var i = 0; i < num; i++) {let randomPoz = Math.floor(Math.random() * library.length);key += library.substring(randomPoz, randomPoz + 1);}return key;},//加密encrypt(word, keyStr) {keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345'; //判断是否存在ksy,不存在就用定义好的keyvar key = CryptoJS.enc.Utf8.parse(keyStr);var srcs = CryptoJS.enc.Utf8.parse(word);var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });return encrypted.toString();},//解密decrypt(word, keyStr) {keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345';var key = CryptoJS.enc.Utf8.parse(keyStr);var decrypt = CryptoJS.AES.decrypt(word, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });return CryptoJS.enc.Utf8.stringify(decrypt).toString();}}

后端 RSA工具类

import lombok.extern.slf4j.Slf4j;import org.ponent;import javax.annotation.PostConstruct;import javax.crypto.Cipher;import java.security.*;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Base64;@Slf4j@Componentpublic class RSA {//定义加密方式public static final String KEY_RSA = "RSA";//定义签名算法private final static String KEY_RSA_SIGNATURE = "MD5withRSA";public static String privateKeyStr;public static String publicKeyStr;/*** 生成公私密钥对*/@PostConstructpublic static void init() throws NoSuchAlgorithmException {KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_RSA);//设置密钥对的bit数,越大越安全,但速度减慢,一般使用512或1024generator.initialize(1024);KeyPair keyPair = generator.generateKeyPair();// 获取公钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();// 获取私钥RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();publicKeyStr = RSA.getPublicKey(publicKey);privateKeyStr = RSA.getPrivateKey(privateKey);log.info("公钥:{}", publicKeyStr);log.info("私钥:{}", privateKeyStr);}/*** 获取Base64编码的公钥字符串*/public static String getPublicKey(RSAPublicKey publicKey) {String str = "";Key key = (Key) publicKey;str = encryptBase64(key.getEncoded());return str;}/*** 获取Base64编码的私钥字符串*/public static String getPrivateKey(RSAPrivateKey privateKey) {String str = "";Key key = (Key) privateKey;str = encryptBase64(key.getEncoded());return str;}/*** BASE64 解码** @param key 需要Base64解码的字符串* @return 字节数组*/public static byte[] decryptBase64(String key) {return Base64.getDecoder().decode(key);}/*** BASE64 编码** @param key 需要Base64编码的字节数组* @return 字符串*/public static String encryptBase64(byte[] key) {return new String(Base64.getEncoder().encode(key));}/*** 公钥加密** @param encryptingStr* @return*/public static String encryptByPublic(String encryptingStr) {try {// 将公钥由字符串转为UTF-8格式的字节数组byte[] publicKeyBytes = decryptBase64(publicKeyStr);// 获得公钥X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);// 取得待加密数据byte[] data = encryptingStr.getBytes("UTF-8");KeyFactory factory;factory = KeyFactory.getInstance(KEY_RSA);PublicKey publicKey = factory.generatePublic(keySpec);// 对数据加密Cipher cipher = Cipher.getInstance(factory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 返回加密后由Base64编码的加密信息return encryptBase64(cipher.doFinal(data));} catch (Exception e) {e.printStackTrace();}return "";}/*** 私钥解密** @param encryptedStr* @return*/public static String decryptByPrivate(String encryptedStr) {try {// 对私钥解密byte[] privateKeyBytes = decryptBase64(privateKeyStr);// 获得私钥PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);// 获得待解密数据byte[] data = decryptBase64(encryptedStr);KeyFactory factory = KeyFactory.getInstance(KEY_RSA);PrivateKey privateKey = factory.generatePrivate(keySpec);// 对数据解密Cipher cipher = Cipher.getInstance(factory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);// 返回UTF-8编码的解密信息return new String(cipher.doFinal(data), "UTF-8");} catch (Exception e) {e.printStackTrace();}return "";}/*** 私钥加密** @param encryptingStr* @return*/public static String encryptByPrivate(String encryptingStr) {try {byte[] privateKeyBytes = decryptBase64(privateKeyStr);// 获得私钥PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);// 取得待加密数据byte[] data = encryptingStr.getBytes("UTF-8");KeyFactory factory = KeyFactory.getInstance(KEY_RSA);PrivateKey privateKey = factory.generatePrivate(keySpec);// 对数据加密Cipher cipher = Cipher.getInstance(factory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);// 返回加密后由Base64编码的加密信息return encryptBase64(cipher.doFinal(data));} catch (Exception e) {e.printStackTrace();}return "";}/*** 公钥解密** @param encryptedStr* @return*/public static String decryptByPublic(String encryptedStr) {try {// 对公钥解密byte[] publicKeyBytes = decryptBase64(publicKeyStr);// 取得公钥X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);// 取得待加密数据byte[] data = decryptBase64(encryptedStr);KeyFactory factory = KeyFactory.getInstance(KEY_RSA);PublicKey publicKey = factory.generatePublic(keySpec);// 对数据解密Cipher cipher = Cipher.getInstance(factory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);// 返回UTF-8编码的解密信息return new String(cipher.doFinal(data), "UTF-8");} catch (Exception e) {e.printStackTrace();}return "";}/*** 用私钥对加密数据进行签名** @param encryptedStr* @return*/public static String sign(String encryptedStr) {String str = "";try {//将私钥加密数据字符串转换为字节数组byte[] data = encryptedStr.getBytes();// 解密由base64编码的私钥byte[] bytes = decryptBase64(privateKeyStr);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);// 指定的加密算法KeyFactory factory = KeyFactory.getInstance(KEY_RSA);// 取私钥对象PrivateKey key = factory.generatePrivate(pkcs);// 用私钥对信息生成数字签名Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);signature.initSign(key);signature.update(data);str = encryptBase64(signature.sign());} catch (Exception e) {e.printStackTrace();}return str;}/*** 校验数字签名** @param encryptedStr* @param sign* @return 校验成功返回true,失败返回false*/public static boolean verify(String encryptedStr, String sign) {boolean flag = false;try {//将私钥加密数据字符串转换为字节数组byte[] data = encryptedStr.getBytes();// 解密由base64编码的公钥byte[] bytes = decryptBase64(publicKeyStr);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);// 指定的加密算法KeyFactory factory = KeyFactory.getInstance(KEY_RSA);// 取公钥对象PublicKey key = factory.generatePublic(keySpec);// 用公钥验证数字签名Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);signature.initVerify(key);signature.update(data);flag = signature.verify(decryptBase64(sign));} catch (Exception e) {e.printStackTrace();}return flag;}}

后端 AES工具类

import org.ponent;import javax.annotation.PostConstruct;import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;import java.security.NoSuchAlgorithmException;import java.util.Base64;import java.util.Random;/*** AES 解密算法类*/@Componentpublic class AES {/*** 秘钥生成来源*/public static final String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";/*** 加解密统一编码方式*/private final static String ENCODING = "utf-8";/*** 加解密方式*/private final static String ALGORITHM = "AES";/*** 加密模式及填充方式*/private final static String PATTERN = "AES/ECB/pkcs5padding";public static String KEY = "";/*** 生成公私密钥对*/@PostConstructpublic static void init() {AES.KEY = AES.generateAESKey();}/*** 生成AES密钥对象** @throws NoSuchAlgorithmException*/public static String generateAESKey() {StringBuffer sb = new StringBuffer();Random random = new Random();for (int i = 0; i < 16; i++) {sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));}return sb.toString();}/*** AES加密** @param plainText* @param key* @return* @throws Exception*/public static String encrypt(String plainText, String key) throws Exception {if (key == null) {System.out.print("Key为空null");return null;}// 判断Key是否为16位if (key.length() != 16) {System.out.print("Key长度不是16位");return null;}SecretKey secretKey = new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM);// AES加密采用pkcs5padding填充Cipher cipher = Cipher.getInstance(PATTERN);//用密匙初始化Cipher对象cipher.init(Cipher.ENCRYPT_MODE, secretKey);//执行加密操作byte[] encryptData = cipher.doFinal(plainText.getBytes(ENCODING));return Base64.getEncoder().encodeToString(encryptData);}/*** AES解密** @param plainText* @param key* @return* @throws Exception*/public static String decrypt(String plainText, String key) throws Exception {SecretKey secretKey = new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM);// 获取 AES 密码器Cipher cipher = Cipher.getInstance(PATTERN);// 初始化密码器(解密模型)cipher.init(Cipher.DECRYPT_MODE, secretKey);// 解密数据, 返回明文byte[] encryptData = cipher.doFinal(Base64.getDecoder().decode(plainText));return new String(encryptData, ENCODING);}}

加密密钥获取

vue 路由拦截器

import router from '../router';import store from '../store/index';/*** vue-router路由版本更新产生的问题,导致路由跳转失败抛出该错误,但并不影响程序功能*/import Router from 'vue-router'//获取原型对象上的push函数const originalPush = Router.prototype.push//修改原型对象中的push方法Router.prototype.push = function push(location) {return originalPush.call(this, location).catch(err => err)}//使用钩子函数对路由进行权限跳转router.beforeEach(async (to, from, next) => {//获取密钥if (!store.state.serviceKey) {await store.dispatch('GET_SERVICE_KEY')}next();});

vuex

import Vue from 'vue';import Vuex from 'vuex';Vue.use(Vuex);import { getServerKey } from '@/api/gateway'import RSA from '../utils/RSAUtil';import AES from "../utils/AESUtil";const modulesFiles = require.context('./modules', true, /\.js$/);const modules = modulesFiles.keys().reduce((modules, modulePath) => {const moduleName = modulePath.replace(/\.\/(.*)\.\w+$/, '$1');const value = modulesFiles(modulePath);modules[moduleName] = value.default;return modules;}, {});export default new Vuex.Store({state: {//密钥serviceKey: ''},getters: {},mutations: {SET_STATE(state, payload) {if (payload) {for (let key in payload) {state[key] = payload[key]}}}},actions: {//获取密钥流程代码,需要多次与后端交互GET_SERVICE_KEY({ commit }) {return getServerKey().then(res => {// 获取随机的AES密钥let resKey = AES.generatekey()// 将AES密钥通过RSA加密发送给服务器return getServerKey(RSA.encrypt(resKey, res.data)).then(res => {// 获取返回结果,通过resKey解密获取服务器的RSA密钥commit('SET_STATE', { serviceKey: AES.decrypt(res.data, resKey) })})})}},modules});

vue api

import axios from 'axios';const dev = process.env.NODE_ENV === 'development';let baseURL = '';if (dev) {baseURL = process.env.VUE_APP_BASE_API;} else {baseURL = process.env.VUE_APP_SRC;}// 获取密钥接口export const getServerKey = (key) => {let config = {timeout: 3000,baseURL: baseURL,url:'/gateway/getServerKey'}if (key) config.params = { key: key };return axios(config)};

java controller

package com.gateway.controller;import com.gateway.util.AES;import com.gateway.util.RSA;import mons.lang3.StringUtils;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/*** @author zhanghao*/@RestController@RequestMapping("/gateway")public class GatewayController {/*** 1.获取RSA的公钥* 2.获取AES的密钥* 2.1 使用RSA密钥解密入参数获取前端生成的AES的key* 2.2 生成新的AES密钥* 2.3 使用前端生成的AES的key加密2.2生成的密钥返回前端** @return*/@GetMapping("/getServerKey")public String getRSAPubKey(String key) throws Exception {if (StringUtils.isBlank(key)) {//1.获取RSA的公钥return RSA.publicKeyStr;} else {//2.获取AES的key//2.1 使用RSA密钥解密入参数获取前端生成的AES的keyString aesKey = RSA.decryptByPrivate(key);return AES.encrypt(AES.KEY, aesKey);}}}

加密拦截

import axios from 'axios';import AES from "../utils/AESUtil";import router from '../router/index';import store from '../store/index';const dev = process.env.NODE_ENV === 'development';let baseURL = '';if (dev) {baseURL = process.env.VUE_APP_BASE_API;} else {baseURL = process.env.VUE_APP_SRC;}const service = axios.create({baseURL: baseURL,timeout: 5 * 1000});service.interceptors.request.use(config => {//process.env.NODE_ENV === 'production' &&if (!dev && config.data) {config.data = { request: AES.encrypt(JSON.stringify(config.data), store.state.serviceKey) };}return config;},err => {return Promise.reject(err);});service.interceptors.response.use(response => {const headers = response.headers;if (!dev && response.data && headers['content-type'].indexOf("application/json") !== -1) {response.data = JSON.parse(AES.decrypt(response.data, store.state.serviceKey))}if (headers['content-type'] === 'application/octet-stream;charset=utf-8') {return response.data;}if (response.data.code === 1) {return Promise.reject(response);} else {return Promise.resolve(response);}},error => {if (error.response) {switch (error.response.status) {case 401:// 返回 401 清除token信息并跳转到登录页面localStorage.removeItem('auth_token');router.replace({path: 'login',query: { redirect: router.currentRoute.fullPath }});break;case 500:return Promise.reject({data: {msg: '500:系统异常!'}});break;case 404:return Promise.reject({data: {msg: '404:系统异常,接口地址未找到。'}});break;case 503:return Promise.reject({data: {msg: '服务异常'}});break;}}// console.log('response22', error);return Promise.reject({data: {msg: error.response.data}});// return Promise.reject(error.response); // 返回接口返回的错误信息});export default service;export const instace = axios.create({baseURL: baseURL,timeout: 60 * 1000 * 5});instace.interceptors.request.use(config => {//process.env.NODE_ENV === 'production' &&if (!dev && config.data) {config.data = { request: AES.encrypt(JSON.stringify(config.data), store.state.serviceKey) };}return config;},err => {return Promise.reject(err);});instace.interceptors.response.use(response => {const headers = response.headers;if (!dev && response.data && headers['content-type'].indexOf("application/json") !== -1) {response.data = JSON.parse(AES.decrypt(response.data, store.state.serviceKey))}if (headers['content-type'] === 'application/octet-stream;charset=utf-8') {return response.data;}if (response.data.code === 1) {return Promise.reject(response);} else {return Promise.resolve(response);}},error => {if (error.response) {switch (error.response.status) {case 401:// 返回 401 清除token信息并跳转到登录页面localStorage.removeItem('auth_token');router.replace({path: 'login',query: { redirect: router.currentRoute.fullPath }});break;case 500:return Promise.reject({data: {msg: '500:系统异常!'}});break;case 404:return Promise.reject({data: {msg: '404:系统异常,接口地址未找到。'}});break;case 503:return Promise.reject({data: {msg: '服务异常'}});break;}}// console.log('response22', error);return Promise.reject({data: {msg: error.response.data}});// return Promise.reject(error.response); // 返回接口返回的错误信息});

java 网关

package com.gateway.config;import com.gateway.config.filter.AppReqDecryptFilter;import com.gateway.config.filter.CorsResponseHeaderFilter;import com.gateway.config.filter.GlobalCacheRequestBodyFilter;import com.gateway.config.filter.TokenFilter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Profile;import org.springframework.web.cors.CorsConfiguration;import org.springframework.web.cors.reactive.CorsWebFilter;import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;@Configurationpublic class CorsConfig {/*** 全局过滤器:缓存请求body*/@Bean@Profile("prod")public GlobalCacheRequestBodyFilter globalCacheRequestBodyFilter() {return new GlobalCacheRequestBodyFilter(-30);}@Bean@Profile("prod")public AppReqDecryptFilter globalAppReqDecryptFilter() {return new AppReqDecryptFilter(-25);}@Beanpublic CorsWebFilter corsWebFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");corsConfiguration.addAllowedOrigin("*");corsConfiguration.setAllowCredentials(true);corsConfiguration.setMaxAge(600L);source.registerCorsConfiguration("/**", corsConfiguration);return new CorsWebFilter(source);}}

package com.gateway.config.filter;import mon.core.constant.ConstantFilter;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.DataBufferUtils;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;import java.util.List;import java.util.Map;/*** @calssName AppCacheRequestBodyFilter* @Description 将 request body 中的内容 copy 一份,记录到 exchange 的一个自定义属性中* @Author ZhangHao* @DATE /9/27 14:42*/public class GlobalCacheRequestBodyFilter implements GlobalFilter, Ordered {private int order;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取请求的方法ServerHttpRequest oldRequest = exchange.getRequest();List<String> nojm = oldRequest.getHeaders().get("nojm");if (nojm != null && nojm.size() > 0) {System.out.println("接口无需解密");Map requestQueryParams = oldRequest.getQueryParams();return chain.filter(exchange);}// 将 request body 中的内容 copy 一份,记录到 exchange 的一个自定义属性中Object cachedRequestBodyObject = exchange.getAttributeOrDefault(ConstantFilter.CACHED_REQUEST_BODY_OBJECT_KEY, null);// 如果已经缓存过,略过if (cachedRequestBodyObject != null) {return chain.filter(exchange);}// 如果没有缓存过,获取字节数组存入 exchange 的自定义属性中return DataBufferUtils.join(exchange.getRequest().getBody()).map(dataBuffer -> {byte[] bytes = new byte[dataBuffer.readableByteCount()];dataBuffer.read(bytes);DataBufferUtils.release(dataBuffer);return bytes;}).defaultIfEmpty(new byte[0]).doOnNext(bytes -> exchange.getAttributes().put(ConstantFilter.CACHED_REQUEST_BODY_OBJECT_KEY, bytes)).then(chain.filter(exchange));}@Overridepublic int getOrder() {return this.order;}public GlobalCacheRequestBodyFilter(int order) {this.order = order;}}

package com.gateway.config.filter;import com.alibaba.fastjson.JSONObject;import mon.core.constant.ConstantFilter;import com.gateway.util.AES;import mon.base.Joiner;import mon.base.Throwables;import mon.collect.Lists;import lombok.extern.slf4j.Slf4j;import mons.lang3.StringUtils;import org.reactivestreams.Publisher;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.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpRequestDecorator;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 .URI;import java.nio.charset.Charset;import java.util.List;import java.util.Map;import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR;/*** 参数解密** @author ZhangHao*/@Slf4jpublic class AppReqDecryptFilter implements GlobalFilter, Ordered {private int order;private static Joiner joiner = Joiner.on("");@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取请求的方法ServerHttpRequest oldRequest = exchange.getRequest();String method = oldRequest.getMethodValue();URI uri = oldRequest.getURI();// 创建新的requestServerHttpRequest newRequest = oldRequest.mutate().uri(uri).build();// 构建新的请求头HttpHeaders headers = new HttpHeaders();headers.putAll(oldRequest.getHeaders());//获取返回ServerHttpResponse originalResponse = exchange.getResponse();DataBufferFactory bufferFactory = originalResponse.bufferFactory();if ("POST".equals(method)) {// 尝试从 exchange 的自定义属性中取出缓存到的 bodyObject cachedRequestBodyObject = exchange.getAttributeOrDefault(ConstantFilter.CACHED_REQUEST_BODY_OBJECT_KEY, null);if (cachedRequestBodyObject != null) {byte[] decrypBytes;try {byte[] body = (byte[]) cachedRequestBodyObject;// 客户端传过来的数据decrypBytes = body;//解密入参JSONObject data = JSONObject.parseObject(new String(decrypBytes));if (data != null && StringUtils.isNotBlank(data.getString("request"))) {String decryptStr = AES.decrypt(data.getString("request"), AES.KEY);decrypBytes = decryptStr.getBytes();}} catch (RuntimeException e) {throw new RuntimeException(e.getMessage());} catch (Exception e) {throw new RuntimeException("系统异常:解密失败");}// 根据解密后的参数重新构建请求Flux<DataBuffer> bodyFlux = Flux.just(bufferFactory.wrap(decrypBytes));newRequest = new ServerHttpRequestDecorator(newRequest) {@Overridepublic Flux<DataBuffer> getBody() {return bodyFlux;}};// 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度int length = decrypBytes.length;headers.remove(HttpHeaders.CONTENT_LENGTH);headers.setContentLength(length);//headers.set(HttpHeaders.CONTENT_TYPE, "application/json");// 把解密后的数据重置到exchange自定义属性中,在之后的日志GlobalLogFilter从此处获取请求参数打印日志exchange.getAttributes().put(ConstantFilter.CACHED_REQUEST_BODY_OBJECT_KEY, decrypBytes);}} else if ("GET".equals(method)) {// todo 暂不处理}//将请求头放入request中newRequest = new ServerHttpRequestDecorator(newRequest) {@Overridepublic HttpHeaders getHeaders() {return headers;}};ServerHttpResponseDecorator response = new ServerHttpResponseDecorator(originalResponse) {@Overridepublic Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {// 获取ContentType,判断是否返回JSON格式数据String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);if (StringUtils.isNotBlank(originalResponseContentType) && originalResponseContentType.contains("application/json")) {Flux<? extends DataBuffer> fluxBody = Flux.from(body);//(返回数据内如果字符串过大,默认会切割)解决返回体分段传输return super.writeWith(fluxBody.buffer().map(dataBuffers -> {List<String> list = Lists.newArrayList();dataBuffers.forEach(dataBuffer -> {try {byte[] content = new byte[dataBuffer.readableByteCount()];dataBuffer.read(content);DataBufferUtils.release(dataBuffer);list.add(new String(content, "UTF-8"));} catch (Exception e) {log.info("加载Response字节流异常,失败原因:{}", Throwables.getStackTraceAsString(e));}});String responseData = joiner.join(list);try {responseData = AES.encrypt(responseData, AES.KEY);} catch (Exception e) {e.printStackTrace();log.error("返回参数结果加密异常:{}", Throwables.getStackTraceAsString(e));}byte[] uppedContent = new String(responseData.getBytes(), Charset.forName("UTF-8")).getBytes();originalResponse.getHeaders().setContentLength(uppedContent.length);return bufferFactory.wrap(uppedContent);}));}}return super.writeWith(body);}@Overridepublic Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {return writeWith(Flux.from(body).flatMapSequential(p -> p));}};return chain.filter(exchange.mutate().request(newRequest).response(response).build());}@Overridepublic int getOrder() {return this.order;}public AppReqDecryptFilter(int order) {this.order = order;}public AppReqDecryptFilter() {}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。