Spring中处理JSON请求通常使用@RequestBody和@ResponseBody注解,针对JSON请求加解密和过滤字符串,Spring提供了RequestBodyAdvice和ResponseBodyAdvice两个接口 
具体使用 
1、解密:


import com.hive.util.AESOperator;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestBodyAdvice; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type; /**
* 请求数据解密
*/
@ControllerAdvice(basePackages = "com.hive")
public class MyRequestBodyAdvice implements RequestBodyAdvice {
private final static Logger logger = LoggerFactory.getLogger(MyResponseBodyAdvice.class);
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
} @Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
} @Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
try {
return new MyHttpInputMessage(inputMessage);
} catch (Exception e) {
e.printStackTrace();
return inputMessage;
}
} @Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
} class MyHttpInputMessage implements HttpInputMessage {
private HttpHeaders headers; private InputStream body; public MyHttpInputMessage(HttpInputMessage inputMessage) throws Exception {
this.headers = inputMessage.getHeaders();
this.body = IOUtils.toInputStream(AESOperator.getInstance().decrypt(IOUtils.toString(inputMessage.getBody(), "UTF-8")), "UTF-8");
} @Override
public InputStream getBody() throws IOException {
return body;
} @Override
public HttpHeaders getHeaders() {
return headers;
}
}
}

2、加密:

package com.hive.core.json;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hive.util.AESOperator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
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; /**
* 返回数据加密
*/
@ControllerAdvice(basePackages = "com.hive")
public class MyResponseBodyAdvice implements ResponseBodyAdvice {
private final static Logger logger = LoggerFactory.getLogger(MyResponseBodyAdvice.class);
private final static String KEY = "!QA2Z@w1sxO*(-8L"; @Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
} @Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
boolean encode = false;
if (returnType.getMethod().isAnnotationPresent(SerializedField.class)) {
//获取注解配置的包含和去除字段
SerializedField serializedField = returnType.getMethodAnnotation(SerializedField.class);
//是否加密
encode = serializedField.encode();
}
if (encode) {
logger.info("对方法method :" + returnType.getMethod().getName() + "返回数据进行加密");
ObjectMapper objectMapper = new ObjectMapper();
try {
String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(body);
return AESOperator.getInstance().encrypt(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
return body;
}
}

注解类:

package com.hive.core.json;

import org.springframework.web.bind.annotation.Mapping;

import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface SerializedField {
/**
* 是否加密
* @return
*/
boolean encode() default true;
}
}

 
默认是true,我这边使用false。注解类中还可以定义需要过滤的字符串

AES加密类

package com.hive.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder; import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; /**
* AES CBC加密
*/
public class AESOperator {
/*
* 加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式,key需要为16位。
*/
private String KEY = "!QA2Z@w1sxO*(-8L";
private String VECTOR = "!WFNZFU_{H%M(S|a";
private static AESOperator instance = null; private AESOperator() { } public static AESOperator getInstance() {
return Nested.instance;
}
//于内部静态类只会被加载一次,故该实现方式时线程安全的!
static class Nested {
private static AESOperator instance = new AESOperator();
} /**
* 加密
*
* @param content
* @return
* @throws Exception
*/
public String encrypt(String content) throws Exception {
return encrypt(content, KEY, VECTOR);
}
/**
* 加密
*
* @param content
* @return
* @throws Exception
*/
public String encrypt(String content,String key) throws Exception {
return encrypt(content, key, VECTOR);
} /**
* 加密
*
* @param content
* @param key
* @param vector
* @return
* @throws Exception
*/
public String encrypt(String content, String key, String vector) throws Exception {
if (key == null) {
return null;
}
if (key.length() != 16) {
return null;
}
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
IvParameterSpec iv = new IvParameterSpec(vector.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8"));
return new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码。
} /**
* 解密
*
* @param content
* @return
* @throws Exception
*/
public String decrypt(String content) throws Exception {
return decrypt(content, KEY, VECTOR);
}
/**
* 解密
*
* @param content
* @return
* @throws Exception
*/
public String decrypt(String content,String key) throws Exception {
return decrypt(content, key, VECTOR);
}
/**
* 解密
*
* @param content
* @param key
* @param vector
* @return
* @throws Exception
*/
public String decrypt(String content, String key, String vector) throws Exception {
try {
if (key == null) {
return null;
}
if (key.length() != 16) {
return null;
}
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
IvParameterSpec iv = new IvParameterSpec(vector.getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] encrypted1 = new BASE64Decoder().decodeBuffer(content);// 先用base64解密
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original, "UTF-8");
return originalString;
} catch (Exception ex) {
return null;
}
} public static void main(String[] args) throws Exception {
// 需要加密的字串
String cSrc = "我爱你"; // 加密
long lStart = System.currentTimeMillis();
String enString = AESOperator.getInstance().encrypt(cSrc,"!QA2Z@w1sxO*(-8L");
System.out.println("加密后的字串是:" + enString); long lUseTime = System.currentTimeMillis() - lStart;
System.out.println("加密耗时:" + lUseTime + "毫秒");
// 解密
lStart = System.currentTimeMillis();
String DeString = AESOperator.getInstance().decrypt(enString);
System.out.println("解密后的字串是:" + DeString);
lUseTime = System.currentTimeMillis() - lStart;
System.out.println("解密耗时:" + lUseTime + "毫秒");
} }

Spring对JSON请求加解密的更多相关文章

  1. spring cloud config 属性加解密

    首先需要(Java Cryptography Extension (JCE))的支持,下载路径: https://www.oracle.com/technetwork/java/javase/down ...

  2. Spring Boot 实现配置文件加解密原理

    Spring Boot 配置文件加解密原理就这么简单 背景 接上文<失踪人口回归,mybatis-plus 3.3.2 发布>[1] ,提供了一个非常实用的功能 「数据安全保护」 功能,不 ...

  3. spring datasource jdbc 密码 加解密

    spring datasource 密码加密后运行时解密的解决办法 - 一号门-程序员的工作,程序员的生活(java,python,delphi实战)http://www.yihaomen.com/a ...

  4. json串加解密

    1.openssl 本身ssl加解密 2.自定义加解密字符串

  5. 学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密

      学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密 技术标签: RSA  AES  RSA AES  混合加密  整合   前言:   为了提高安全性采用了RS ...

  6. React中的AES加解密请求

    引言 在我们使用React开发Web前端的时候,如果是比较大的项目和正常的项目的话,我们必然会用到加解密,之前的文章中提到.NET的一些加解密,那么,这里我就模拟一个例子: 1.后台开发API接口,但 ...

  7. Spring Cloud Config 配置中心 自动加解密功能 JCE方式

    1.首先安装JCE JDK8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.h ...

  8. Spring Cloud Config 配置中心 自动加解密功能 jasypt方式

    使用此种方式会存在一种问题:如果我配置了自动配置刷新,则刷新过后,加密过后的密文无法被解密.具体原因分析,看 SpringCloud 详解配置刷新的原理 使用  jasypt-spring-boot- ...

  9. SpringBoot中如何灵活的实现接口数据的加解密功能?

    数据是企业的第四张名片,企业级开发中少不了数据的加密传输,所以本文介绍下SpringBoot中接口数据加密.解密的方式. 本文目录 一.加密方案介绍二.实现原理三.实战四.测试五.踩到的坑 一.加密方 ...

随机推荐

  1. 10折交叉验证(10-fold Cross Validation)与留一法(Leave-One-Out)、分层采样(Stratification)

    10折交叉验证 我们构建一个分类器,输入为运动员的身高.体重,输出为其从事的体育项目-体操.田径或篮球. 一旦构建了分类器,我们就可能有兴趣回答类似下述的问题: . 该分类器的精确率怎么样? . 该分 ...

  2. Html5画钟表盘/指针实时跳动

    1.最终效果 时钟.分钟.秒指针连续移动2.完整代码 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml&q ...

  3. recovery uncrypt功能解析(bootable/recovery/uncrypt/uncrypt.cpp)

    我们通常对一个文件可以直接读写操作,或者普通的分区(没有文件系统)也是一样,直接对/dev/block/boot直接读写,就可以获取里面的数据内容了. 当我们在ota升级的时候,把升级包下载到cach ...

  4. pycharm运行Django发生AppRegistryNotReady: Apps aren't loaded yet.

    pycharm中运行django默认情况下并不是执行项目的,所以如果在非manage.py,会发生异常. raise AppRegistryNotReady("Apps aren't loa ...

  5. python:序列化与数据持久化

    数据持久化的方式有: 1.普通文件无格式写入:将数据直接写入到文件中 2.普通序列化写入:json,pickle 3.DBM方式:shelve,dbm 相关内容: json pickle shelve ...

  6. mac挂载分区包括EFI 或者任何隐藏分区

    1.mac终端下的diskutil命令是用来操作磁盘的 diskutil list #显示当前pc所有的磁盘 2.例如我们要挂载u盘中的efi分区 ,确定你的efi分区的 identified 我的是 ...

  7. Websocket通信过程

    1. 客户端与服务器建立连接 2. 客户端通过session向服务器发送消息 3. 服务器接收客户端的消息,调用服务器端的onMessage()方法包装.生成消息内容(新的消息包括客户端ID) 4. ...

  8. python第四十八天--高级FTP

    高级FTP服务器1. 用户加密认证2. 多用户同时登陆3. 每个用户有自己的家目录且只能访问自己的家目录4. 对用户进行磁盘配额.不同用户配额可不同5. 用户可以登陆server后,可切换目录6. 查 ...

  9. [HDFS_add_2] SecondaryNameNode 滚动 NameNode 数据流程

    0. 说明 在 将 SecondaryNameNode 配置到 s105 节点上 的基础上进行 SecondaryNameNode 滚动 NameNode 数据流程 分析 1. SecondaryNa ...

  10. 【PAT】B1043 输出PATest(20 分)

    /* */ #include<stdio.h> #include<algorithm> #include<string.h> #include<ctype.h ...