VUE和Spring Boot前后端交互报文加密

您所在的位置:网站首页 前后端交互加密方法是什么 VUE和Spring Boot前后端交互报文加密

VUE和Spring Boot前后端交互报文加密

2023-09-10 08:53| 来源: 网络整理| 查看: 265

背景

公司在做研发平台,提供给金融行业业务系统使用,涉及敏感数据较多,需要对前后端数据交互报文进行加密处理。本文采用目前较流行的方式AES + BASE64算法进行加密。 VUE端采用:cryptoJS Spring Boot端采用:hutool(糊涂)开源工具

1、VUE 1.1、引入cryptoJS npm install crypto-js --save-dev 1.2、编写加密/解密函数 //前后端定义的密钥,AES使用16位 const CRYPTOJSKEY= "ABCDEFG"; // 加密 function encrypt(plaintText) { var plaintText = plaintText; var options = { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }; var key = CryptoJS.enc.Utf8.parse(CRYPTOJSKEY); var encryptedData = CryptoJS.AES.encrypt(plaintText, key, options); var encryptedBase64Str = encryptedData.toString().replace(/\//g, "_"); encryptedBase64Str = encryptedBase64Str.replace(/\+/g,"-"); return encryptedBase64Str; } //解密 function decrypt(encryptedBase64Str) { var vals = encryptedBase64Str.replace(/\-/g, '+').replace(/_/g, '/'); var options = { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }; var key = CryptoJS.enc.Utf8.parse(CRYPTOJSKEY); var decryptedData = CryptoJS.AES.decrypt(vals, key, options); var decryptedStr = CryptoJS.enc.Utf8.stringify(decryptedData); return decryptedStr } 1.3、前端数据进行加密

采用请求前拦截操作,encrypt(JSON.stringify(config.data))

// request interceptorinstance.interceptors.request.use( config => { // Do something before request is sent if (store.getters.token) { config.headers["Authorization"] = `Bearer ${getToken()}`; // 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改 } config.data = encrypt(JSON.stringify(config.data)) return config; }, error => { // Do something with request error Message.error("对不起,出错了"); console.log(error); // for debug Promise.reject(error); } ); 1.4、Axios请求加密 export const createAPI = (url, method, data) => { let config = {}; if (method === "get") { config.params = data; } else { config.data = data; } config.headers = { "Content-Type": "application/json;" }; return instance({ url, method, ...config }); }; 2、Spring Boot 2.1、引入hutool cn.hutool hutool-all 5.4.7 2.2、处理方案(即拦截)定位

分析: 1、数据加密/解密主要是针对请求/响应的body进行处理。 2、springboot前后端对接点为Controler。 3、如何实现在Controler接收前就实现拦截处理呢?

方案一

可以采用拦截器、过滤器等方案。

方案二、(采用方案)

1、采用才做 RequestBodyAdvice与ResponseBodyAdvice

RequestBodyAdvice:

package org.springframework.web.servlet.mvc.method.annotation; import java.io.IOException; import java.lang.reflect.Type; import org.springframework.core.MethodParameter; import org.springframework.http.HttpInputMessage; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.lang.Nullable; public interface RequestBodyAdvice { boolean supports(MethodParameter var1, Type var2, Class> var3); HttpInputMessage beforeBodyRead(HttpInputMessage var1, MethodParameter var2, Type var3, Class> var4) throws IOException; Object afterBodyRead(Object var1, HttpInputMessage var2, MethodParameter var3, Type var4, Class> var5); @Nullable Object handleEmptyBody(@Nullable Object var1, HttpInputMessage var2, MethodParameter var3, Type var4, Class> var5); }

ResponseBodyAdvice:

package org.springframework.web.servlet.mvc.method.annotation; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.lang.Nullable; public interface ResponseBodyAdvice { boolean supports(MethodParameter var1, Class> var2); @Nullable T beforeBodyWrite(@Nullable T var1, MethodParameter var2, MediaType var3, Class> var4, ServerHttpRequest var5, ServerHttpResponse var6); }

在beforeBodyRead和beforeBodyWrite两个接口中有接收和返回报文,可以在里面实现报文解密加密。

自定义请求实现类DecryptRequestBodyAdvice.java:

/** * 请求数据接收处理类 * * 对加了@Decrypt的方法的数据进行解密操作 * * 只对 @RequestBody 参数有效 * @author xxm */ @ControllerAdvice public class DecryptRequestBodyAdvice implements RequestBodyAdvice { @Value("${crypto.charset}") private String charset = "UTF-8"; @Value("${crypto.key}") private String key; @Override public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { return true; } @Override public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { return body; } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) throws IOException { // if( NeedCrypto.needDecrypt(parameter) ){ // return new DecryptHttpInputMessage(inputMessage , charset , key); // } // return inputMessage; return new DecryptHttpInputMessage(inputMessage , charset , key);//请求信息解密,参考DecryptHttpInputMessage解密类 } @Override public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { return body; } }

自定义响应实现类EncryptResponseBodyAdvice.java:

/** * 请求响应处理类 * * 对加了@Encrypt的方法的数据进行加密操作 * * @author 熊诗言 * */ @ControllerAdvice public class EncryptResponseBodyAdvice implements ResponseBodyAdvice { @Value("${crypto.charset}") private String charset = "UTF-8"; @Value("${crypto.key}") private String key; @Override public boolean supports(MethodParameter returnType, Class> converterType) { return NeedCrypto.needEncrypt(returnType); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //TODO 实现具体的加密方法 System.out.println("________________"); return body; } }

注:必须加入@ControllerAdvice注解,没有它是没有注入到spring中的。

自定义请求信息解密类,DecryptHttpInputMessage.java:

/** * * @author xxm */ public class DecryptHttpInputMessage implements HttpInputMessage { private HttpInputMessage inputMessage; private String charset; private String key; public DecryptHttpInputMessage(HttpInputMessage inputMessage, String charset , String key) { this.inputMessage = inputMessage; this.charset = charset; this.key = key; } @Override public InputStream getBody() throws IOException { //使用hutool开始解密 String content = IoUtil.read(inputMessage.getBody() , charset); byte[] bytes = SecureUtil.aes(key.getBytes(charset)).decrypt(content); return new ByteArrayInputStream(bytes); } @Override public HttpHeaders getHeaders() { return inputMessage.getHeaders(); }


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3