Springboot项目如何加密返回值和请求参数
创始人
2024-03-12 02:44:29
0

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、encrypt-spring-boot-starter
  • 二、自定义加密方式
    • 1.为什么要自定义加密方式
    • 2.改造后的代码
  • 总结


前言

本公司项目要求越来越严格,并且其中一条为加密,要求请求参数和返回值加密。今天简单的记录


一、encrypt-spring-boot-starter

加密传输使用前端加密,后端解密的方式。后端加密前端解密的方式。并且加密后不能被普通工具解密,需要使用密钥进行解密,保证数据的安全。那么现在encrypt-spring-boot-starter可以直接使用。

二、自定义加密方式

1.为什么要自定义加密方式

查看该依赖的源码,发现,只有使用依赖自定的res工具类包装返回值,并且他支持加密方式为AES,并不满足我们项目使用SM2的要求,同时,无法自定义加密方式。所以选择根据他的代码进行改造

2.改造后的代码

首先,需要知道,我们通过在接口上进行注解的方式,来定义改接口是否使用加密和解密。那么首先定义加密和解密的注解

//加密
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.PARAMETER})
public @interface Decrypt {
}
//解密
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Encrypt {
}

使用aop进行切面解密和加密

package com.hisw.talent.encrypt;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;/*** @description:接口解密* @date 2022/11/25 14:03*/
@EnableConfigurationProperties(EncryptProperties.class)
@ControllerAdvice
public class DecryptRequest extends RequestBodyAdviceAdapter {@AutowiredEncryptProperties encryptProperties;  public DecryptRequest() {}public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) {return methodParameter.hasMethodAnnotation(Decrypt.class) || methodParameter.hasParameterAnnotation(Decrypt.class);}public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) throws IOException {byte[] body = new byte[inputMessage.getBody().available()];inputMessage.getBody().read(body);try {//this.encryptProperties.getKey() 这个key 根据你使用的加密方式来自定义AES需要满足16位,当然//AESUtils.decrypt 可以替换为你需要的加密工具类,比如使用SM2,或者RSA非对称加密byte[] decrypt = AESUtils.decrypt(body, this.encryptProperties.getKey().getBytes());final ByteArrayInputStream bais = new ByteArrayInputStream(decrypt);return new HttpInputMessage() {public InputStream getBody() throws IOException {return bais;}public HttpHeaders getHeaders() {return inputMessage.getHeaders();}};} catch (Exception var8) {var8.printStackTrace();return super.beforeBodyRead(inputMessage, parameter, targetType, converterType);}}
}
package com.hisw.talent.encrypt;import com.fasterxml.jackson.databind.ObjectMapper;
import com.hisw.talent.common.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/*** @description:接口加密* @date 2022/11/25 14:02*/
@EnableConfigurationProperties(EncryptProperties.class)
@ControllerAdvice
public class EncryptResponse implements ResponseBodyAdvice {private ObjectMapper om = new ObjectMapper();@AutowiredEncryptProperties encryptProperties;public EncryptResponse() {}public boolean supports(MethodParameter returnType, Class> converterType) {return returnType.hasMethodAnnotation(Encrypt.class);}public Result beforeBodyWrite(Result body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {byte[] keyBytes = this.encryptProperties.getKey().getBytes();try {
/*            if (body.getMsg() != null) {body.setMsg(org.javaboy.encrypt.starter.utils.AESUtils.encrypt(body.getMsg().getBytes(), keyBytes));}*/if (body.getData() != null) {//这个步骤可以替换为你的工具类 ,同时 Result 返回工具类替换为你项目中的body.setData(AESUtils.encrypt(this.om.writeValueAsBytes(body.getData()), keyBytes));}} catch (Exception var9) {var9.printStackTrace();}return body;}
}

最后,在你controller 里 打上 注解来控制接口的加密和解密


总结

方式为切面编程,难度不大,但是目前有个问题,AES加密 一旦 body数据太大,那么解密时会出现失败的情况,提示长度需要为16的倍数。RSA加密boby太长,需要使用分段解密。同时会造成前端解密后出现乱码的情况。SM2加密,同样会遇到解密失败的情况。需要04开头,但是过程中依然会报错。希望知道的同学解惑

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...