前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VUE和Spring Boot 实现加密

VUE和Spring Boot 实现加密

原创
作者头像
ruochen
发布2021-12-16 22:25:38
2.9K0
发布2021-12-16 22:25:38
举报
1、VUE
1.1、引入cryptoJS
代码语言:txt
复制
npm install crypto-js --save-dev
1.2、编写加密/解密函数
代码语言:txt
复制
//前后端定义的密钥,AES使用16位
代码语言:txt
复制
const CRYPTOJSKEY= "ABCDEFG";
代码语言:txt
复制
// 加密
代码语言:txt
复制
function encrypt(plaintText) {
代码语言:txt
复制
    var plaintText = plaintText;
代码语言:txt
复制
    var options = {
代码语言:txt
复制
        mode: CryptoJS.mode.ECB,
代码语言:txt
复制
        padding: CryptoJS.pad.Pkcs7
代码语言:txt
复制
    };
代码语言:txt
复制
  var key = CryptoJS.enc.Utf8.parse(CRYPTOJSKEY);
代码语言:txt
复制
  var encryptedData = CryptoJS.AES.encrypt(plaintText, key, options);
代码语言:txt
复制
  var encryptedBase64Str = encryptedData.toString().replace(/\//g, "_");
代码语言:txt
复制
  encryptedBase64Str = encryptedBase64Str.replace(/\+/g,"-");
代码语言:txt
复制
  return encryptedBase64Str;
代码语言:txt
复制
}
代码语言:txt
复制
//解密
代码语言:txt
复制
function decrypt(encryptedBase64Str) {
代码语言:txt
复制
  var vals = encryptedBase64Str.replace(/\-/g, '+').replace(/_/g, '/');
代码语言:txt
复制
  var options = {
代码语言:txt
复制
      mode: CryptoJS.mode.ECB,
代码语言:txt
复制
      padding: CryptoJS.pad.Pkcs7
代码语言:txt
复制
  };
代码语言:txt
复制
  var key = CryptoJS.enc.Utf8.parse(CRYPTOJSKEY);
代码语言:txt
复制
  var decryptedData = CryptoJS.AES.decrypt(vals, key, options);
代码语言:txt
复制
  var decryptedStr = CryptoJS.enc.Utf8.stringify(decryptedData);
代码语言:txt
复制
  return decryptedStr
代码语言:txt
复制
}  
1.3、前端数据进行加密

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

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

分析:

1、数据加密/解密主要是针对请求/响应的body进行处理。

2、springboot前后端对接点为Controler。

3、如何实现在Controler接收前就实现拦截处理呢?

方案一

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

方案二、(采用方案)

1、采用才做 RequestBodyAdvice与ResponseBodyAdvice

RequestBodyAdvice:

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

ResponseBodyAdvice:

代码语言:txt
复制
package org.springframework.web.servlet.mvc.method.annotation;
代码语言:txt
复制
import org.springframework.core.MethodParameter;
代码语言:txt
复制
import org.springframework.http.MediaType;
代码语言:txt
复制
import org.springframework.http.converter.HttpMessageConverter;
代码语言:txt
复制
import org.springframework.http.server.ServerHttpRequest;
代码语言:txt
复制
import org.springframework.http.server.ServerHttpResponse;
代码语言:txt
复制
import org.springframework.lang.Nullable;
代码语言:txt
复制
public interface ResponseBodyAdvice<T> {
代码语言:txt
复制
   boolean supports(MethodParameter var1, Class<? extends HttpMessageConverter<?>> var2);
代码语言:txt
复制
   @Nullable
代码语言:txt
复制
   T beforeBodyWrite(@Nullable T var1, MethodParameter var2, MediaType var3, Class<? extends HttpMessageConverter<?>> var4, ServerHttpRequest var5, ServerHttpResponse var6);
代码语言:txt
复制
}

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

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

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

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

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

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

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

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、VUE
    • 1.1、引入cryptoJS
      • 1.2、编写加密/解密函数
        • 1.3、前端数据进行加密
          • 1.4、Axios请求加密
          • 2、Spring Boot
            • 2.1、引入hutool
              • 2.2、处理方案(即拦截)定位
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档