加密方式 AES

spring jar 包 pom.xml配置(注意版本)

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc-portlet</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.2.5.RELEASE</version>
            <scope>test</scope>
        </dependency>

这个是原理图

在spring做如下 配置。

    <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
        <property name="order" value="0" />
    </bean>
    <bean class="com.sifude.youlife.spring.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        
        <property name="messageConverters">
            <list>
                <ref bean="jsonHttpMessageConverter" />
                <ref bean="stringHttpMessageConverter" />
                <!-- <ref bean="marshallingHttpMessageConverter" /> -->
            </list>
        </property>
    </bean>
    <bean id="stringHttpMessageConverter"
        class="org.springframework.http.converter.StringHttpMessageConverter">
        <constructor-arg value="UTF-8" />
        <property name="supportedMediaTypes">
            <value>text/html;charset=UTF-8</value>
        </property>
    </bean>
    <bean id="jsonHttpMessageConverter"
        class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>

可以发现com.sifude.youlife.spring.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter这个类就是我们自己写的。从spring里面拷贝出如下几个类

RequestParamMethodArgumentResolver对每个参数进行了拦截,然后在resolveName方法进行处理,因此我们只要

重写RequestParamMethodArgumentResolver中的resolveName方法即可

    @Override
    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {         Object arg;         HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        MultipartHttpServletRequest multipartRequest =
            WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);         if (MultipartFile.class.equals(parameter.getParameterType())) {
            assertIsMultipartRequest(servletRequest);
            Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
            arg = multipartRequest.getFile(name);
        }
        else if (isMultipartFileCollection(parameter)) {
            assertIsMultipartRequest(servletRequest);
            Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
            arg = multipartRequest.getFiles(name);
        }
        else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
            assertIsMultipartRequest(servletRequest);
            arg = servletRequest.getParameter(name);
        }
        else {
            arg = null;
            if (multipartRequest != null) {
                List<MultipartFile> files = multipartRequest.getFiles(name);
                if (!files.isEmpty()) {
                    arg = (files.size() == 1 ? files.get(0) : files);
                }
            }
            if (arg == null) {
                boolean isEnc = false;
                if (null != parameter.getMethod().getAnnotation(EncRequest.class)) {
                    isEnc = true;
                }
                if (isEnc) {// 数据需要加密的情况
                    String content = servletRequest.getParameter("content");
                    if (null != content) {
                        content = AESUtil.decrypt(content);
                        ObjectMapper mapper = new ObjectMapper(); // can reuse, share
                        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 忽略未知元素
                        Object o = mapper.readValue(content, HashMap.class).get(name);
                        if(o instanceof String[]) {
                            String[] paramValues = (String[]) o;
                            if (paramValues != null) {
                                arg = paramValues.length == 1 ? paramValues[0] : paramValues;
                            }
                        } else {
                            arg = o;
                        }
                    }
                } else {
                    String[] paramValues = webRequest.getParameterValues(name);
                    if (paramValues != null) {
                        arg = paramValues.length == 1 ? paramValues[0] : paramValues;
                    }
                }
            }
        }         return arg;
    }

其他1个注解和加密算法

package com.sifude.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EncRequest { }
package com.sifude.tool.util;

import java.io.UnsupportedEncodingException;
import java.util.Random; import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.sifude.tool.util.entity.Constant; /**
 * AES加解密算法
 * key:每次登陆动态随机生成(大小写字母和数字组成),并保存在session中
 * 此处使用AES-128-CBC加密模式,key需要为16位
 */
public class AESUtil {
    private static Logger log = LoggerFactory.getLogger(FileUtil.class);
    
    public static boolean isAES = Constant.AES.ISAES;
    public static String sKey = Constant.AES.SKEY;
    
    // 加密
    public static String encrypt(String sSrc) throws Exception {
        
        if(!isAES) {
            return sSrc;
        }
        if (sKey == null) {
            //System.out.print("Key为空null");
            return null;
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            //System.out.print("Key长度不是16位");
            return null;
        }
        byte[] raw = sKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
        IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        //加密前要进行编码,否则js无法解码
        byte[] encrypted = cipher.doFinal(sSrc.getBytes("UTF-8"));         return Base64.encodeBase64String(encrypted);// 此处使用BAES64做转码功能,同时能起到2次加密的作用。
    }     // 解密
    public static String decrypt(String sSrc) throws Exception {
        if(!isAES) {
            return sSrc;
        }
        // 判断Key是否正确
        if (sKey == null) {
            //System.out.print("Key为空null");
            return null;
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            //System.out.print("Key长度不是16位");
            return null;
        }
        byte[] raw = sKey.getBytes("ASCII");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec("0102030405060708"
                .getBytes());
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] encrypted1 = Base64.decodeBase64(sSrc);// 先用bAES64解密
        //System.out.println(encrypted1.length);
        byte[] original = cipher.doFinal(encrypted1);
        String originalString = new String(original);
        return originalString;
    }     // 生成随机密锁
    public static String getKey(int length) {
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        // 参数length,表示生成几位随机数
        for (int i = 0; i < length; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            // 输出字母还是数字
            if ("char".equalsIgnoreCase(charOrNum)) {
                // 输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                sb.append((char) (random.nextInt(26) + temp));
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                sb.append(String.valueOf(random.nextInt(10)));
            }
        }         try {
            return new String(sb.toString().getBytes(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(), e);
        }
        return "mapabc2014214yxj";
    }     public static void main(String[] args) {
        //AES.sKey = getKey(16);
        AESUtil.isAES = true;
        try {
            //String str = AES.encrypt("你好1.2#3:4//5_6,1 2&3?4a/bc5=6");
            //String str = AES.encrypt("{\"account\":\"ez\",\"password\":\"123456\"}");
            String str = AESUtil.encrypt("{\"cityId\":\"110000\",\"cityType\":\"1\"}");
            System.out.println(str);
            String str1 = AESUtil.decrypt(str);
            System.out.println(str1);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    } }

这样功能就实现了,欢迎大家一期交流。

Spring 接口参数加密传输的更多相关文章

  1. 如何写出安全的API接口?接口参数加密签名设计思路

    开发中经常用到接口,尤其是在面向服务的soa架构中,数据交互全是用的接口. 几年以前我认为,我写个接口,不向任何人告知我的接口地址,我的接口就是安全的,现在回想真是too young,too simp ...

  2. 如何写出安全的 API 接口?接口参数加密签名设计思路

    原文链接:http://blog.csdn.net/ma_jiang/article/details/53636840

  3. 如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)- 续(附demo)

    上篇文章说到接口安全的设计思路,如果没有看到上篇博客,建议看完再来看这个. 通过园友们的讨论,以及我自己查了些资料,然后对接口安全做一个相对完善的总结,承诺给大家写个demo,今天一并放出. 对于安全 ...

  4. 基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密

    在日常开发中,有时候我们经常需要和第三方接口打交道,有时候是我们调用别人的第三方接口,有时候是别人在调用我们的第三方接口,那么为了调用接口的安全性,一般都会对传输的数据进行加密操作,如果每个接口都由我 ...

  5. 分享如何使用PHP将URL地址参数进行加密传输提高网站安全性

    大家在使用PHP进行GET或POST提交数据时,经常会在URL带着参数进行传递,比如www.mdaima.com/get.php?id=1&page=5,这里就将id编号和page页码进行了参 ...

  6. Spring Boot 之:接口参数校验

    Spring Boot 之:接口参数校验,学习资料 网址 SpringBoot(八) JSR-303 数据验证(写的比较好) https://qq343509740.gitee.io/2018/07/ ...

  7. java 调用Spring接口上传文件及其他参数填充

    第一步:在Spring配置中添加以下内容 <!-- 配置MultipartResolver 用于文件上传 使用spring的CommosMultipartResolver --> < ...

  8. spring 接口校验参数(自定义注解)

    1. 注解类 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.l ...

  9. Spring Boot实现通用的接口参数校验

    Spring Boot实现通用的接口参数校验 Harries Blog™ 2018-05-10 2418 阅读 http ACE Spring App API https AOP apache IDE ...

随机推荐

  1. 如果没有<form>标签,也没有enctype="multipart/form-data"属性,怎么使用formData对象提交表单呢?如下方式

    form标签的enctype属性 enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码. 默认地,表单数据会编码为 "application/x-www-form-urlen ...

  2. JSONP方法简单封装

    function myJsonp(url, data, callback) { //参数判断 if (Object.prototype.toString.call(data) == "[ob ...

  3. JS监听浏览器的返回、后退、上一页按钮的事件方法

    在实际的应用中,我们常常需要实现在移动app和浏览器中点击返回.后退.上一页等按钮实现自己的关闭页面.调整到指定页面或执行一些其它操作的需求,那在代码中怎样监听当点击微信.支付宝.百度糯米.百度钱包等 ...

  4. VMware与Hyper-V的冲突解决 VMware Workstation 与 Device/Credential Guard 不兼容 解决方案

    win10专业版官方解决方案https://kb.vmware.com/s/article/2146361 win10家庭版解决方案win10家庭版本身是不支持Hyper-V服务的,但是如果是“win ...

  5. QT安装后再添加或删除组件

    QT安装目录下打开MaintenanerceTool.exe 手动添加​储存库,要定位一个储存有QT在线安装镜像的网址: https://download.qt.io/online/qtsdkrepo ...

  6. oracle 启动三步骤

    oracle 启动三步骤 oracle启动会经过三个过程,分别是nomount.mount.open 一.nomount 阶段 nomount 阶段,可以看到实例已经启动.oracle进程会根据参数文 ...

  7. 前端工具mock的使用 - 造数据模拟网络请求

    前后端同步开发过程中,有时候前端页面完成了,需要等待后端接口完成部署后才能联调. 这个时候如果不想等待,想自己造数据模拟网络请求,这种情况就能用到mock工具了. mock工具可以用在web网站,也能 ...

  8. nltk 词性解析

    转载链接: https://blog.csdn.net/pengjian444/article/details/81143983

  9. 区块链基础认识-BTC

    1.什么是区块链 a.定义: 从本质上来说区块链就是一种通过将用户的某种特定信息(比如交易信息),通过很多台计算机记录保存并同步的过程,每个区块都记录了对应的交易信息,将这些交易信息串联起来就形成了所 ...

  10. datatable中的copy和clone的用法区分

    dt.copy();//复制结构和数据 dt.clone();//仅复制结构,不复制数据