加密方式 AES
spring jar 包 pom.xml配置(注意版本)
org.springframework spring-core 3.2.5.RELEASE org.springframework spring-jdbc 3.2.5.RELEASE org.springframework spring-orm 3.2.5.RELEASE org.springframework spring-context 3.2.5.RELEASE org.springframework spring-context-support 3.2.5.RELEASE org.springframework spring-beans 3.2.5.RELEASE org.springframework spring-aspects 3.2.5.RELEASE org.springframework spring-aop 3.2.5.RELEASE org.springframework spring-webmvc 3.2.5.RELEASE org.springframework spring-web 3.2.5.RELEASE org.springframework spring-tx 3.2.5.RELEASE org.springframework spring-webmvc-portlet 3.2.5.RELEASE org.springframework spring-oxm 3.2.5.RELEASE org.springframework spring-jms 3.2.5.RELEASE org.springframework spring-test 3.2.5.RELEASE test
这个是原理图
在spring做如下 配置。
text/html;charset=UTF-8
text/html;charset=UTF-8 application/json;charset=UTF-8
可以发现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其他1个注解和加密算法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; }
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)@Documentedpublic @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); } }}
这样功能就实现了,欢迎大家一期交流。