springmvc 部分加密通信
2016-03-30 12:23
357 查看
手机客户端与后台交互中一般会用到加密传输。至于不用HTTPS,本文不讨论,这里给出使用springmvc +http协议,手机客户端加密部分数据值,后台进行统一解密。实现思路就是使用拦截器,使用装饰模式,可以直接使用HttpServletRequestWrapper。
密文:HM6LxeRjJxc=
UR编码: HM6LxeRjJxc%3d
密文: HNf8wVhKhsg=
UR编码: HNf8wVhKhsg%3d
密文:
密文URL编码后:
或者
密文RFC822格式(76个字符一行):
密文RFC822格式URL编码后:
springmvc, phone 使用原文, 其他三个使用加密数据
POST:
期望结果:
POSTMAN:
结果:
解密拦截器源码:
springmvc后台DES3 解密
原文和密文前后均无空格数据
#1
原文: karl密文:HM6LxeRjJxc=
UR编码: HM6LxeRjJxc%3d
#2
原文: del555密文: HNf8wVhKhsg=
UR编码: HNf8wVhKhsg%3d
#3
原文:在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。然后,每次取出6个bit
密文:
eT9O6eHyB27BKL7u4eXE49xoGZZ4aZdQ3ibZ4uKvlD8yLwCeKJi9SYijf142uufEB36d/sk6VmuOd8c8WHspd3kba490j/3+Dez03ycGzNssE4MwuNApSdyQ5BDZTLq7fkxwn+MvkIJTGiwgPcdD8xEMEWgp6/s9gENhWGGnayBfWrSv/36pBNNVhb+HkKXlwPCAazIVbFK4CrohlviiJ3lJv7/qfFlPNPUAVQYAWbGBJ7vA4osfspzMb0abw3uXSROm7KYopKu9KRe9Cgxs7w==
密文URL编码后:
eT9O6eHyB27BKL7u4eXE49xoGZZ4aZdQ3ibZ4uKvlD8yLwCeKJi9SYijf142uufEB36d%2Fsk6VmuOd8c8WHspd3kba490j%2F3%2BDez03ycGzNssE4MwuNApSdyQ5BDZTLq7fkxwn%2BMvkIJTGiwgPcdD8xEMEWgp6%2Fs9gENhWGGnayBfWrSv%2F36pBNNVhb%2BHkKXlwPCAazIVbFK4CrohlviiJ3lJv7%2FqfFlPNPUAVQYAWbGBJ7vA4osfspzMb0abw3uXSROm7KYopKu9KRe9Cgxs7w%3D%3D
或者
密文RFC822格式(76个字符一行):
eT9O6eHyB27BKL7u4eXE49xoGZZ4aZdQ3ibZ4uKvlD8yLwCeKJi9SYijf142uufEB36d/sk6VmuO d8c8WHspd3kba490j/3+Dez03ycGzNssE4MwuNApSdyQ5BDZTLq7fkxwn+MvkIJTGiwgPcdD8xEM EWgp6/s9gENhWGGnayBfWrSv/36pBNNVhb+HkKXlwPCAazIVbFK4CrohlviiJ3lJv7/qfFlPNPUA VQYAWbGBJ7vA4osfspzMb0abw3uXSROm7KYopKu9KRe9Cgxs7w==
密文RFC822格式URL编码后:
eT9O6eHyB27BKL7u4eXE49xoGZZ4aZdQ3ibZ4uKvlD8yLwCeKJi9SYijf142uufEB36d%2fsk6VmuO%0ad8c8WHspd3kba490j%2f3%2bDez03ycGzNssE4MwuNApSdyQ5BDZTLq7fkxwn%2bMvkIJTGiwgPcdD8xEM%0aEWgp6%2fs9gENhWGGnayBfWrSv%2f36pBNNVhb%2bHkKXlwPCAazIVbFK4CrohlviiJ3lJv7%2fqfFlPNPUA%0aVQYAWbGBJ7vA4osfspzMb0abw3uXSROm7KYopKu9KRe9Cgxs7w%3d%3d
测试
使用已以上数据进行测试springmvc, phone 使用原文, 其他三个使用加密数据
@Controller public class IndexController { @RequestMapping("/") @ResponseBody Object index(String phone, String name, String password, String desc) { System.out.println("-----------------------------------------"); System.out.println("phone:" + phone); System.out.println("name:" + name); System.out.println("password:" + password); System.out.println("desc:" + desc); return "Hello longdai!"; } }
POST:
参数 | 值 |
---|---|
phone | 131212345678 |
name | HM6LxeRjJxc%3d |
password | HNf8wVhKhsg%3d |
desc | 这里使用数据#3的URL编码后的数据 |
----------------------------------------- phone:131212345678 name:karl password:del555 desc:在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。然后,每次取出6个bit
POSTMAN:
结果:
解密拦截器源码:
@Configuration public class DecryptFilter extends OncePerRequestFilter { private static Log log = LogFactory.getLog(DecryptFilter.class); private static Pattern BASE64_PATTERN = Pattern.compile("^[a-zA-Z0-9\\+/]+[=]{0,2}$"); private static Pattern BASE64_PATTERN_RFC822 = Pattern.compile("^[a-zA-Z0-9\\+/\n]+[=]{0,2}$"); public String filter(HttpServletRequest request, String name, String input) { String ret = input; if (input == null || input.trim().equals("(null)")) { return null; } boolean b1 = input.length()%4==0 && BASE64_PATTERN.matcher(input).matches(); boolean b2 = input.length() > 77 && input.charAt(76)=='\n' && BASE64_PATTERN_RFC822.matcher(input).matches(); if ( !b1 && !b2){ return injectSQLFilter(name, input);//not base64 text } try { ret = Des3.decode(input); } catch (Exception e) { log.error(request.getRequestURI() + " error decode " + name + "=" + input, e); } return injectSQLFilter(name, ret); } public String injectSQLFilter(String name, String text){ if(text==null){ return null; } if(name.matches("password|passwd|loginPassword|dealPassword")){ return text; } //TODO 这里处理SQL注入,直接处理掉注入数据,或者下层拦截器处理 return text; } @Override protected void doFilterInternal(final HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { chain.doFilter(new HttpServletRequestWrapper(request) { protected Map<String, String[]> parameters = new HashMap<String, String[]>(); @Override public String getParameter(String name) { if (parameters.containsKey(name)){ String[] values = parameters.get(name); if (values!=null && values.length>0){ return values[0]; } } String value = super.getParameter(name); String retValue = filter(this, name, value); parameters.put(retValue, new String[]{retValue}); return retValue; } @Override public String[] getParameterValues(String name) { if (parameters.containsKey(name)){ String[] values = parameters.get(name); return values; } String[] values = super.getParameterValues(name); if (values == null) { return null; } for (int i = 0; i < values.length; i++) { values[i] = filter(this, name, values[i]); } parameters.put(name, values); return values; } }, response); } }
相关文章推荐
- Java多线程编程基础之线程对象
- java大数相乘
- JAVA中使用Scanner连续输入int和String错误的解决方案
- 关于Class.getResource和ClassLoader.getResource的路径问题
- JAVA中的Scanner类(IO)[JAVA][译]
- Java中Synchronized的用法
- 关于springmvc的controller返回页面无法跳转,使用ajax
- EL操作符
- spring4整合hibernate5.1
- l.ExecException: Process 'command 'C:\Java\jdk1.8.0_45\bin\java.exe'' 错误
- 针对异常java.lang.IllegalStateException onMeasure() did not set the measured dimension解决方法
- java学习笔记(四)
- Eclipse编译apk提示Unable to execute dex: Multiple dex files define 解决方法
- JDK 动态代理的简单理解
- java中的注解
- java中的注解
- Java 动态绑定 静态绑定
- Java图形界面基础案例分析(满天星)
- 【springboot】自定义模板配置
- Java三大主流框架概述