Spring对JSON请求加解密

来源:互联网 发布:知敬畏守底线强党性 编辑:程序博客网 时间:2024/06/05 19:58

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@Mappingpublic @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 + "毫秒");    }}
0 0
原创粉丝点击