springboot中request和response的加解密实现代码

目录
  • 1、新建一个springboot工程,pom依赖如下
  • 2、自定义加密、解密的注解
  • 3、加密算法
  • 4、对请求数据进行解密处理
  • 5、对响应数据进行加密处理
  • 6、加解密的key的配置类,从配置文件中读取
  • 7、测试

在系统开发中,需要对请求和响应分别拦截下来进行解密和加密处理,在springboot中提供了RequestBodyAdviceAdapter和ResponseBodyAdvice,利用这两个工具可以非常方便的对请求和响应进行预处理。

1、新建一个springboot工程,pom依赖如下

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2、自定义加密、解密的注解

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

其中加密注解放在方法上,解密注解可以放在方法上,也可以放在参数上。

3、加密算法

定义一个加密工具类,加密算法分为对称加密和非对称加密,本次使用java自带的Ciphor来实现对称加密,使用AES算法,如下

public class AESUtils {
    private static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";
    private static final String key = "1234567890abcdef";
    /**
     * 获取 cipher
     * @param key
     * @param model
     * @return
     * @throws Exception
     */
    private static Cipher getCipher(byte[] key, int model) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(model, secretKeySpec);
        return cipher;
    }
    /**
     * AES加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String encrypt(byte[] data, byte[] key) throws Exception {
        Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE);
        return Base64.getEncoder().encodeToString(cipher.doFinal(data));
    }
    /**
     * AES解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE);
        return cipher.doFinal(Base64.getDecoder().decode(data));
    }
}

其中加密后的数据使用Base64算法进行编码,获取可读字符串;解密的输入也是一个Base64编码之后的字符串,先进行解码再进行解密。

4、对请求数据进行解密处理

@EnableConfigurationProperties(KeyProperties.class)
@ControllerAdvice
public class DecryptRequest extends RequestBodyAdviceAdapter {

    @Autowired
    private KeyProperties keyProperties;

    /**
     * 该方法用于判断当前请求,是否要执行beforeBodyRead方法
     *
     * @param methodParameter handler方法的参数对象
     * @param targetType      handler方法的参数类型
     * @param converterType   将会使用到的Http消息转换器类类型
     * @return 返回true则会执行beforeBodyRead
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.hasMethodAnnotation(Decrypt.class) || methodParameter.hasParameterAnnotation(Decrypt.class);
    }

    /**
     * 在Http消息转换器执转换,之前执行
     * @param inputMessage
     * @param parameter
     * @param targetType
     * @param converterType
     * @return 返回 一个自定义的HttpInputMessage
     * @throws IOException
     */
    @Override
    public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        byte[] body = new byte[inputMessage.getBody().available()];
        inputMessage.getBody().read(body);
        try {
            byte[] keyBytes = keyProperties.getKey().getBytes();
            byte[] decrypt = AESUtils.decrypt(body, keyBytes);
            final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decrypt);
            return new HttpInputMessage() {
                @Override
                public InputStream getBody() throws IOException {
                    return byteArrayInputStream;
                }

                @Override
                public HttpHeaders getHeaders() {
                    return inputMessage.getHeaders();
                }
            };
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.beforeBodyRead(inputMessage, parameter, targetType, converterType);
    }
}

5、对响应数据进行加密处理

@EnableConfigurationProperties(KeyProperties.class)
@ControllerAdvice
public class EncryptResponse implements ResponseBodyAdvice<RespBean> {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private KeyProperties keyProperties;

    /**
     * 该方法用于判断当前请求的返回值,是否要执行beforeBodyWrite方法
     *
     * @param methodParameter handler方法的参数对象
     * @param converterType   将会使用到的Http消息转换器类类型
     * @return 返回true则会执行beforeBodyWrite
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.hasMethodAnnotation(Encrypt.class);
    }

    /**
     * 在Http消息转换器执转换,之前执行
     * @param body
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return 返回 一个自定义的HttpInputMessage,可以为null,表示没有任何响应
     */
    @Override
    public RespBean beforeBodyWrite(RespBean body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        byte[] keyBytes = keyProperties.getKey().getBytes();
        try {
            if (body.getMsg() != null) {
                body.setMsg(AESUtils.encrypt(body.getMsg().getBytes(), keyBytes));
            }
            if (body.getObj() != null) {
                body.setObj(AESUtils.encrypt(objectMapper.writeValueAsBytes(body.getObj()), keyBytes));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }
}

6、加解密的key的配置类,从配置文件中读取

@ConfigurationProperties(prefix = "spring.encrypt")
public class KeyProperties {

    private final static String DEFAULT_KEY = "1234567890abcdef";
    private String key = DEFAULT_KEY;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}

7、测试

application中的key配置

spring.encrypt.key=1234567890abcdef
	@GetMapping("/user")
    @Encrypt
    public RespBean getUser() {
        User user = new User();
        user.setId(1L);
        user.setUsername("caocao");
        return RespBean.ok("ok", user);
    }

    @PostMapping("/user")
    public RespBean addUser(@RequestBody @Decrypt User user) {
        System.out.println("user = " + user);
        return RespBean.ok("ok", user);
    }

测试结果

其中get请求的接口使用了@Encrypt注解,对响应数据进行了加密处理;post请求的接口使用了@Decrypt注解作用在参数上,对请求数据进行了解密处理。

到此这篇关于springboot中request和response的加解密实现的文章就介绍到这了,更多相关springboot加解密内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Springboot使用filter对response内容进行加密方式

    目录 使用filter对response内容进行加密 编写加密类(AES) 编写Filter类 写配置类 Springboot数据加密传输 创建加解密注解注解 创建request解密类 创建response加密类 创建AES加密工具类 创建加解密Filter类 定义过滤器的拦截路径 使用filter对response内容进行加密 编写加密类(AES) /** * aes加密解密 */ public class AesEncryptUtils { //参数分别代表 算法名称/加密模式/数据填充方式

  • SpringBoot实现接口数据的加解密功能

    一.加密方案介绍 对接口的加密解密操作主要有下面两种方式: 自定义消息转换器 优势:仅需实现接口,配置简单. 劣势:仅能对同一类型的MediaType进行加解密操作,不灵活. 使用spring提供的接口RequestBodyAdvice和ResponseBodyAdvice 优势:可以按照请求的Referrer.Header或url进行判断,按照特定需要进行加密解密. 比如在一个项目升级的时候,新开发功能的接口需要加解密,老功能模块走之前的逻辑不加密,这时候就只能选择上面的第二种方式了,下面主要

  • SpringBoot获取Request和Response方法代码解析

    通过静态方法获取,你也可以封装一个静态方法出来 @GetMapping(value = "") public String center() { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); HttpServletRequest request = servletRequestAttrib

  • SpringBoot ResponseBody返回值处理的实现

    1. SpringBoot ResponseBody 返回值中null值处理 @PostMapping(path = "/test", produces = MediaType.APPLICATION_JSON_VALUE) public Object test() { JSONObject jsonObject = new JSONObject(); jsonObject.put("test","test"); jsonObject.put(&

  • 详解SpringBoot中添加@ResponseBody注解会发生什么

    SpringBoot版本2.2.4.RELEASE. [1]SpringBoot接收到请求 ① springboot接收到一个请求返回json格式的列表,方法参数为JSONObject 格式,使用了注解@RequestBody 为什么这里要说明返回格式.方法参数.参数注解?因为方法参数与参数注解会影响你使用不同的参数解析器与后置处理器!通常使用WebDataBinder进行参数数据绑定结果也不同. 将要调用的目标方法如下: @ApiOperation(value="分页查询") @Re

  • springboot中request和response的加解密实现代码

    目录 1.新建一个springboot工程,pom依赖如下 2.自定义加密.解密的注解 3.加密算法 4.对请求数据进行解密处理 5.对响应数据进行加密处理 6.加解密的key的配置类,从配置文件中读取 7.测试 在系统开发中,需要对请求和响应分别拦截下来进行解密和加密处理,在springboot中提供了RequestBodyAdviceAdapter和ResponseBodyAdvice,利用这两个工具可以非常方便的对请求和响应进行预处理. 1.新建一个springboot工程,pom依赖如下

  • JSP 中request与response的用法详解

    JSP 中request与response的用法详解 概要: 在学习这两个对象之前,我们应该已经有了http协议的基本了解了,如果不清楚http协议的可以看我的关于http协议的介绍.因为其实request和response的使用大部分都是对http协议的操作. request对象的介绍 我们先从request对象进行介绍: 我们知道http协议定义了请求服务器的格式: 请求行 请求头 空格 请求体(get请求没有请求体) 好了,这里我们就不详细介绍了,我们只看几个应用就可以了,没什么难度: 应

  • 在springboot中实现个别bean懒加载的操作

    懒加载---就是我们在spring容器启动的是先不把所有的bean都加载到spring的容器中去,而是在当需要用的时候,才把这个对象实例化到容器中. @Lazy 在需要懒加载的bean上加上@Lazy就可以了 补充知识:springboot组件懒加载的坑及加载规则 什么是懒加载? 懒加载的意思是不在项目启动的时候实例出来这个组件 @RestController public class ApiController { @Autowired Skill kobSkillImpl; @Request

  • SpringBoot中整合Shiro实现权限管理的示例代码

    之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧 一.简介 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序. 三个核心组件: 1.Subject 即"当前操作用户".但是,在 Shi

  • PHP 7.1中利用OpenSSL代替Mcrypt加解密的方法详解

    概要: php7.1发布后新特性吸引了不少PHPer,大家都在讨论新特性带来的好处与便利.但是从php7.0 升级到 php7.1 废弃(过时)了一个在过去普遍应用的扩展(mcrypt扩展).官方提供了相应的解决提示,却没有提供更详细的解决办法.于是坑来了: 今天在使用微信开放平台对接一个内容管理系统的时候,在绑定公众号的时候一直失败 原因: 调试的时候发现,直接原因是因为开放平台里面填写的授权事件(该授权事件每十分钟会通送一次事件来更新ticket),即: 这个地方填写的url,调试发现,这个

  • SpringBoot中使用Cookie实现记住登录的示例代码

    最近在做项目,甲方提出每次登录都要输入密码,会很麻烦,要求实现一个记住登录状态的功能,于是便使用 Cookie 实现该功能 一.Cookie 简介 Cookie,一种储存在用户本地终端上的数据,有时也用其复数形式 Cookies.类型为"小型文本文件",是某些网站为了辨别用户身份,进行 Session 跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息. 其实 Cookie 就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器.然后客户端

  • React中Suspense及lazy()懒加载及代码分割原理和使用方式

    目录 React.lazy() 概括 为什么需要懒加载 如何进行代码分割 Suspense Suspense应用场景 Suspense实现原理 总结 Suspense和lazy()都是react中比较新的特性,在项目中使用还比较少,但是学习一下有助于在后面的项目中使用,同样可以一窥React未来的发展方向 React.lazy() 概括 顾名思义lazy()方法是用来对项目代码进行分割,懒加载用的.只有当组件被加载,内部的资源才会导入 为什么需要懒加载 在React的项目中import导入其他组

  • 小论asp中request与response的用法

    request的用法: request有三种获取表单值的方法,分别用于不同的表单递交方法的获取.表单简单地可以认为是指页面所要传递的参数的一个集合,而其递交的方法有两个post和get.在这两种方法里面,分别对应着不同的接收方法,其具体的实现如下: 1.对于post方法递交的表单的获取值方法,运用request的form属性的get方法获取所要字段标识.例如,获取提交表单中的txtUserName的值放到字符串usrName中的代码如下,string userName=Request.Form.

  • android md5加密与rsa加解密实现代码

    复制代码 代码如下: import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5 { /* * MD5加密 */ public static String getDigest(String str) { MessageDigest messageDigest = nul

随机推荐