spring实现接口加密

http://my.oschina.net/u/2288185/blog/488552

加密方式 AES

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
         < 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做如下 配置。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     <!-- 启动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方法即可

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
     @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个注解和加密算法
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 {
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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);
         }
     }
 
}

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值