SpringBoot+Vue使用AES进行接口加密

目录

前言

一、前端工作准备

1.下载crypto-js

2.加密解密工具类

3.对axios请求拦截加密

二、后端工作准备

1.所需依赖

2.实现RequestBodyAdvice

3.实现HttpInputMessage

三、数据响应加密(扩展)

[1.实现 ResponseBodyAdvice(后端)](#1.实现 ResponseBodyAdvice(后端))

2.axios响应拦截器(前端)


前言

在数字化时代,数据安全已成为企业和社会关注的焦点。为了确保数据的机密性和完整性,我们采用SpringBoot和Vue技术,结合AES对称加密,构建一个高效且安全的系统。AES加密算法以其高度的安全性和广泛的应用场景,成为了数据加密的首选方案。通过在SpringBoot后端实现AES加密和解密逻辑,我们能够确保数据在传输和存储过程中的安全。同时,在Vue前端,我们利用相应的加密和解密方法,实现了与后端的无缝对接。这样,无论是数据的发送还是接收,都能够得到充分的保护。这种加密方案不仅提高了系统的安全性,也增强了用户的信任度。

一、前端工作准备

1.下载crypto-js

javascript 复制代码
npm install crypto-js --save-dev

2.加密解密工具类

keyOne是自己设置的一个key,可以根据你自己的业务来设置

javascript 复制代码
import cryptoJs from 'crypto-js'
// 加密
let keyOne = '313233343536373a'
export function encrypt(word) {
    let key = cryptoJs.enc.Utf8.parse(keyOne)
    let enc = ''
    if (typeof word === 'string') {
        enc = cryptoJs.AES.encrypt(word, key, {
            // iv: iv
            mode: cryptoJs.mode.ECB,
            padding: cryptoJs.pad.Pkcs7
        })
    } else if (typeof word === 'object') {
        let data = JSON.stringify(word)
        enc = cryptoJs.AES.encrypt(data, key, {
            // iv: iv
            mode: cryptoJs.mode.ECB,
            padding: cryptoJs.pad.Pkcs7
        })
    }
    let encryptedData = enc.ciphertext;
    var encryptedBase64Str = encryptedData.toString().replace(/\//g, "_");
    encryptedBase64Str = encryptedBase64Str.replace(/\+/g,"-");
    console.log(encryptedBase64Str)
    return encryptedBase64Str;
}

//解密
export function decrypt(word) {
    console.log('传入的密文:', word)
    let key = cryptoJs.enc.Hex.parse(keyOne)
    let dec = cryptoJs.AES.decrypt(cryptoJs.format.Hex.parse(word), key, {
        // vi: vi
        mode: cryptoJs.mode.ECB,
        padding: cryptoJs.pad.Pkcs7
    })
    return cryptoJs.enc.Utf8.stringify(dec)
}

3.对axios请求拦截加密

这边我设置有一个拦截器,并且我只对Post请求进行拦截,其他请求不拦截,如果你想要其他请求(get、put、delete)进行拦截,则可以仿照Post请求来进行数据加密

javascript 复制代码
const whiteList = ['/user/login',"/upload/oss"]; //排除的路径
// 请求拦截器
service.interceptors.request.use(
    config => {
        if (store.getters.token) {
            // 设置令牌请求头
            config.headers['authorization'] = store.getters.token;
        }

        if (config.method === 'post' && whiteList.indexOf(config.url)===-1 && config.data){
            config.headers['Content-Type'] = 'application/json;charset=UTF-8';
            config.data = encrypt(config.data)
        }
        return config
    },
    error => {
        return Promise.reject(error)
    }
);

二、后端工作准备

1.所需依赖

XML 复制代码
        <!--        hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.17</version>
        </dependency>

2.自定义注解

该注解用于在Post请求的方法上添加,open字段为是否打开解密,默认为true(打开)。

java 复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AESCrypto {
	boolean open() default true;
}

3.实现RequestBodyAdvice

javascript 复制代码
package com.pzg.chat.handler;
@Slf4j
@ControllerAdvice
public class DecryptRequestBodyAdviceHandler implements RequestBodyAdvice {

	@Value("${crypto.charset}")
	private String charset = "UTF-8";
	@Value("${crypto.key}")
	private String key;

	@Override
	public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
		return true;
	}

	@Override
	public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {

		AESCrypto methodAnnotation = methodParameter.getMethodAnnotation(AESCrypto.class);
		if (methodAnnotation!=null && BooleanUtil.isTrue(methodAnnotation.open())){
			return new DecryptHttpInputMessageHandler(inputMessage , charset , key);//请求信息解密,参考DecryptHttpInputMessage解密类
		}
		return inputMessage;
	}

	@Override
	public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
		return body;
	}

	@Override
	public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
		return body;
	}
}

4.实现HttpInputMessage

javascript 复制代码
public class DecryptHttpInputMessageHandler implements HttpInputMessage {

	private HttpInputMessage inputMessage;
	private String charset;
	private String key;

	public DecryptHttpInputMessageHandler(HttpInputMessage inputMessage, String charset , String key) {
		this.inputMessage = inputMessage;
		this.charset = charset;
		this.key = key;
	}
	@Override
	public InputStream getBody() throws IOException {
		//使用hutool开始解密
		InputStream body = inputMessage.getBody();
		String content = IoUtil.read(body , charset);
		byte[] bytes = SecureUtil.aes(key.getBytes(charset)).decrypt(content);

		return new ByteArrayInputStream(bytes);
	}

	@Override
	public HttpHeaders getHeaders() {
		return inputMessage.getHeaders();
	}
}

最后当前端发送post请求到后端后,就会被我们定义的 DecryptRequestBodyAdviceHandler 类所拦截,并获取其中信息并进行解密。

三、数据响应加密(扩展)

1.实现 ResponseBodyAdvice<Object>(后端)

javascript 复制代码
@ControllerAdvice
public class EncryptResponseBodyAdviceHandler implements ResponseBodyAdvice<Object> {
	@Override
	public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
		return true;
	}

	@Override
	public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        sout("-------------->你的加密逻辑")
		return null;
	}
}

2.axios响应拦截器(前端)

javascript 复制代码
axios.interceptors.response.use(
  (response) => {
    console.log("----------->解密逻辑")
    switch (response.data.code) {
      case 40001:
        Vue.prototype.$message({
          type: 'error',
          message: response.data.message
        })
        router.push({ path: '/login' })
        break
      case 50000:
        Vue.prototype.$message({
          type: 'error',
          message: response.data.message
        })
        break
    }
    return response
  },
  (error) => {
    return Promise.reject(error)
  }
)
相关推荐
有味道的男人7 分钟前
搜好货平台关键词商品搜索接口:分页容错与商品数据轻量化提取方案
服务器·前端·javascript
silvamux_10 分钟前
Spring Boot 调用大模型 api 最小可跑教程
java·spring boot·后端
今年下半年12 分钟前
【Spring Boot 】通过 OpenFeign 请求第三方接口
java·spring boot·后端·openfeign
lovingsoft1 小时前
Chrome Lighthouse 详解
前端·chrome
Qlly1 小时前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝1 小时前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦1 小时前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡1 小时前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95272 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端