Maven项目的RSA加密及解密(用户数据)的配置流程:
Maven项目的RSA加密及解密(用户数据)的配置流程:
做过快三年多的程序员了,之前同事们都喜欢发表博客文章 而鄙人特例。 总喜欢看文章,毕竟有现成的粮食,干嘛还多此一举额,呵呵。
也就没想着注册一下账号 于是前不久注册这个账号了 也是没怎更好的利用起来 ; 这不心血来潮 ,突然意识到不发表些博客文章 感觉就不是一个完整的程序员 ,因此就有了以下文章 。
头一次发表 若有人查阅 如有什不足之处,多提意见, 多多见谅。。。
第一步:
获得公钥私钥(秘钥格式:PKCS#8 测试:建议是无私钥密码的,省一些麻烦)
公钥:
—–BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAy8GL3N2/M1IgrG3ixFUJ8crC
wuEXZqGUnvjH0wDraN3U4fFixvg0PD+LvXhpBOBhsxC8Txg66HgWUnWwAU/+Fy4g
litH3oAoNI9ouM71fFCuO01q/YKEKFOpYvRlrXmc013HU0TSZLmSFt30j7mHSjsj
QwlfWTO7rZmU/KRGPwIDAQAB
—–END PUBLIC KEY—–
私钥:
—–BEGIN PRIVATE KEY—–
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMDLwYvc3b8zUiCs
beLEVQnxysLC4RdmoZSe+MfTAOto3dTh8WLG+DQ8P4u9eGkE4GGzELxPGDroeBZS
dbABT/4XLiCWK0fegCg0j2i4zvV8UK47TWr9goQoU6li9GWteZzTXcdTRNJkuZIW
3fSPuYdKOyNDCV9ZM7utmZT8pEY/AgMBAAECgYBMyVpe0CrpWhFdvg9OABA2k7zD
8UYhQdkdDmvbemilWfDwNsUjKEf21gAhMedhPHX5s4340i++VpRtn44L+ZnX0g4m
j3bh4hiY7G+X+Ia0sCA//oBnLOHTvnrkKm4sbDd5R1YAgMXCMDxunYeodnytKeyh
nNYBpuHkBXVPOEThMQJBAO570+r7K25wDmH3jxr0USfFaYt2ogoazr4D0GNP3Bjz
i6f15IHz4vcW0InY6t06FqJU00zX7Y2XgZIq0sEDOsUCQQDO9N4y5HYH9aE3oHUM
KghwWXGyXZCzcwA+rl4ieeysUXGrThLjJNmiunt3L2MzYQ8uZ3biP4ECFiqyJNxs
bl0zAkEAsEbDO7twPO+DEhLkqm3Q1u7qtvV3jLSIAJfdHqtW6vKKVhpBT3UwXKd2
eY3m/KMFO/QrQ2+P3csRMTOKGLUEaQJAaWCxi0Rc/SyLDGH9d1Ynud0xUVrnBRh3
dXMfp3phklReBpXYdCQdVQiTOVq9rjmrmzs/g3BGZiOXVeIDAosnlQJAZiFjZVwu
4sFJu+1IQA/IoHFBadJlVTQk5qMEBEMlNWprGdEPS2LAzQywp0UoIKukd6m0N858
Ln0hh1pBvGPMMQ==
—–END PRIVATE KEY—–
(RSA公钥私钥获得来源: http://web.chacuo.net/netrsakeypair)
如图:
第三步:导入工具类:
RsaDecryptRequestParamFilter.java 用于过滤请求 过滤掉不需要加密数据的请求地址,需要在web.xml文件配置
主要解读doFilter方法,根据需求结合下面的web.xml文件,以便于更快速解读
package com.lc.utils; import java.io.IOException; import java.lang.reflect.Field; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpMethod; public class RsaDecryptRequestParamFilter implements Filter { private static Field requestField; private static Field parametersParsedField; private static Field coyoteRequestField; private static Field parametersField; private static Field hashTabArrField; private List<String> noNeedRsaUrl; public void init(FilterConfig filterConfig) throws ServletException { try { @SuppressWarnings("rawtypes") Class clazz = Class.forName("org.apache.catalina.connector.RequestFacade"); requestField = clazz.getDeclaredField("request"); requestField.setAccessible(true); parametersParsedField = requestField.getType().getDeclaredField("parametersParsed"); parametersParsedField.setAccessible(true); coyoteRequestField = requestField.getType().getDeclaredField("coyoteRequest"); coyoteRequestField.setAccessible(true); parametersField = coyoteRequestField.getType().getDeclaredField("parameters"); parametersField.setAccessible(true); hashTabArrField = parametersField.getType().getDeclaredField("paramHashValues"); hashTabArrField.setAccessible(true); noNeedRsaUrl = Arrays.asList(replaceBlank(filterConfig.getInitParameter("noNeedRsaUrl")).split(",")); System.out.println("RsaFilter初始化完成,不需要解密的Post方法为:{}"+ noNeedRsaUrl); } catch (Exception e) { e.printStackTrace(); } } @SuppressWarnings("unchecked") public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; servletResponse.setCharacterEncoding("UTF-8"); //String url = ((HttpServletRequest) servletRequest).getServletPath(); //获得post请求路径url String url = req.getServletPath(); //判断是否匹配 不需要加密的post请求 if (!noNeedRsaUrl.contains(url)) { //url请求不匹配 不需要加密的post请求 就会获得url的data密文(/user/tologin.action) Object rsaKey = req.getParameter("data");//密文:rsaKey if (req.getMethod().equals(HttpMethod.POST.name())) { //判断是否有密文 if (null != rsaKey) { String[] params; try {
String paramValue = RSAUtil.decryptRequestParamValue((String) rsaKey);//调用工具类RSAUtil 传参(密文) 解密 params = paramValue.split("&"); } catch (Exception e) { e.printStackTrace(); servletResponse.getWriter().write("{\"code\":\"403\",\"message\":\"密文错误\"}"); return; } Map<String, ArrayList<String>> requestParamtersMap = getRequestMap(servletRequest); for (int i = 0; i < params.length; i++) { String[] param = params[i].split("="); if (param.length == 2){ @SuppressWarnings("rawtypes") ArrayList list = new ArrayList<Object>(); list.add(URLDecoder.decode(param[1], "UTF-8")); requestParamtersMap.put(param[0], list); } } } else { servletResponse.getWriter().write("{\"code\":\"403\",\"message\":\"缺少密文\"}"); return; } } } //请求url路径成功匹配不需要加密的post请求,即放过不需要加密的url请求 filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { } @SuppressWarnings("unchecked") private Map<String, ArrayList<String>> getRequestMap(ServletRequest request) { try { Object innerRequest = requestField.get(request); parametersParsedField.setBoolean(innerRequest, true); Object coyoteRequestObject = coyoteRequestField.get(innerRequest); Object parameterObject = parametersField.get(coyoteRequestObject); return (Map<String, ArrayList<String>>) hashTabArrField.get(parameterObject); } catch (IllegalAccessException e) { e.printStackTrace(); return Collections.emptyMap(); } } public String replaceBlank(String str) { String dest = ""; if (str!=null) { Pattern p = Pattern.compile("\\s*|\t|\r|\n"); Matcher m = p.matcher(str); dest = m.replaceAll(""); } return dest; } }
RSAUtil.java 用于解密 密文 还原数据(注:把获得的私钥覆盖给RSAUtil.java 的REQUEST_PRIVATE_KEY)
package com.lc.utils; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import javax.crypto.Cipher; import sun.misc.BASE64Decoder; @SuppressWarnings("restriction") public class RSAUtil { private static String REQUEST_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALWS2K8hwWbqmYxp" + "+s4dYtbl0emqTaoV5klD9dhjOsoXuuPqO/mpGvQ/aKEHWLD62XPwUprEc869ZOZE" + "nN+MWw2EfJ8/AejIM9OFzYse2/tTMdUdJ9RNYQfl7XFthiQc1ATLvpjSr+gBod/y" + "azXF79niirkyohjaYQ1gwSkFwAK7AgMBAAECgYBYErOyN3BlaFQ0rM9wHQbtcCqi" + "6e2kG91JGoLshC1nC52mod6XmjQt13f76+FUb0j9GMwosDPwSyPfIdbqBF3BXoad" + "3S0ZX9N42Kbdqmv7ywHxbNI73NXyyXeQ0B51KgL0pvpa8fBHscZcMRlVGjhv1P8u" + "wpHkEWnrwmbCqK7zQQJBAN67U1eY0HRdNvsa248jvvYkwbcuV6wHJZMUWGpvMZl8" + "3Dj4rcje4RNApXgeJNMlCMTWhqZ+Dq77w1lIA+duCdsCQQDQsb4pumUKu8f8vYGw" + "SgsijCRkbE1sJVMUbPVbAM6byejqAyV+UaNWicSb3sTyZK/gnOr7RLCd2K4/V2j6" + "dHChAkEAkBQpU27c2Yk6+bBj+vIqo1sfnHlz6SouWjg9AYywTxN/+bKT6G6UtjmJ" + "UGxfcd5xD7OeIrFEmljuAyEctWZvJQJBAKcAVUhXHFxGgHbDv3AvEFIJC2ZBNIOC" + "KsWBm6XDM5J/NJ9u/SXkdmzdujNxRPEjmYqIh5GjGiJ2LpoJfLxPSYECQQCUYcXq" + "tFVB0ep1NW+YzU260n3funhWRTxOpfOaHrp5g60kg5Jxvw7MD7eRuUH0BwHoYP1w" + "qsgUkbjigqZQCK3u"; /** * 解密算法 * cryptograph:密文 */ public static String decryptRequestParamValue(String cryptograph) throws Exception { PrivateKey key = stringToPrivateKey(REQUEST_PRIVATE_KEY); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, key); BASE64Decoder decoder = new BASE64Decoder(); byte[] b1 = decoder.decodeBuffer(cryptograph); byte[] b = cipher.doFinal(b1); return new String(b); } public static PrivateKey stringToPrivateKey(String s) { BASE64Decoder decoder = new BASE64Decoder(); byte[] c = null; KeyFactory keyFact = null; PrivateKey returnKey = null; try { c = decoder.decodeBuffer(s); keyFact = KeyFactory.getInstance("RSA"); } catch (Exception e) { System.out.println("Error in first try catch of stringToPrivateKey"); e.printStackTrace(); } PKCS8EncodedKeySpec x509KeySpec = new PKCS8EncodedKeySpec(c); try { // the next line causes the crash returnKey = keyFact.generatePrivate(x509KeySpec); } catch (Exception e) { System.out.println("Error in stringToPrivateKey"); e.printStackTrace(); } return returnKey; } }
第四步:配置web.xml文件
<!--加载RsaDecryptRequestParamFilter--> <filter> <filter-name>RSA</filter-name> <filter-class>com.lc.utils.RsaDecryptRequestParamFilter</filter-class> <init-param> <description>过滤不需要加密的post请求</description> <param-name>noNeedRsaUrl</param-name> <param-value>/user/tologin.action</param-value> </init-param> </filter> <filter-mapping> <filter-name>RSA</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
第五步:下载js:http://files.cnblogs.com/files/ytwy/jsencrypt.min.zip 解压放入项目webapp下
下载如图:
最后一步:
例如做的是有关用户登录的数据加密:
关于登录用的form表单的代码 根据需要 自我定义
以下是登录form表单中数据的加密操作及ajax提交的代码:
<!--引入下载的jsencrypt.min.js 为数据创造加密环境--> <script type="text/javascript" src="<%=request.getContextPath() %>/jsencrypt/jsencrypt.min.js"></script> <script type="text/javascript"> $(function() { $("#login").click(function() {/*登录按钮触发事件 */ var encrypt=new JSEncrypt(); /*放入获得的公钥*/ encrypt.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1ktivIcFm6pmMafrOHWLW5dHpqk2qFeZJQ/XYYzrKF7rj6jv5qRr0P2ihB1iw+tlz8FKaxHPOvWTmRJzfjFsNhHyfPwHoyDPThc2LHtv7UzHVHSfUTWEH5e1xbYYkHNQEy76Y0q/oAaHf8ms1xe/Z4oq5MqIY2mENYMEpBcACuwIDAQAB"); /*放入,获得有关用户登录的表单数据*/ encrypted=encrypt.encrypt($("form").serialize()); $.post( "<%=request.getContextPath() %>/user/dologin.action", {"data":encrypted}, function(data) { if(data){ alert("登录成功!!!");location.href="<%=request.getContextPath() %>/user/console.action"; }else{ alert("此用户不存在,请注册后,再登录!!!");location.reload(); } }, "json" ); }); }); </script>
有关Maven项目的RSA加密解密(用户数据)的配置流程结束。。。。。。
以下是对其效果的小小测试的:
弹出的密文就是上面代码定义的效果的体现
然后post请求路径被RsaDecryptRequestParamFilter.java类 过滤 ,因容错机制不匹配后,被调用的RSAUtil解密 密文
即解密效果:
。。。。。。
不煮米饭的电饭锅