加密方式 AEShtml
spring jar 包 pom.xml配置(注意版本)java
<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>
這個是原理圖web
在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裏面拷貝出以下幾個類spring
RequestParamMethodArgumentResolver對每一個參數進行了攔截,而後在resolveName方法進行處理,所以咱們只要apache
重寫RequestParamMethodArgumentResolver中的resolveName方法便可json
@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); } } }
這樣功能就實現了,歡迎你們一期交流。
session