第一步:
獲得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)
如圖:
第二步:向Maven項目中導入工具類:
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> NeedRsaUrl; public void init(FilterConfig filterConfig) throws ServletException { try { 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); NeedRsaUrl = Arrays.asList(replaceBlank(filterConfig.getInitParameter("NeedRsaUrl")).split(",")); System.out.println("RsaFilter初始化完成,不需要解密的Post方法為:{}"+ NeedRsaUrl); } catch (Exception e) { e.printStackTrace(); } } 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請求路徑 String url = req.getServletPath(); //判斷是否包含需要加密的post請求 if (NeedRsaUrl.contains(url)) { System.out.println("需要加密的請求NeedRsaUrl分別有:"+NeedRsaUrl); System.out.println("此時加密請求路徑是"+url); //包含需要加密的post請求(/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; } } } //不需要加密的post請求匹配成功,放過不需要加密的post請求 filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { } 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; } }
第三步:配置web.xml文件
此路徑/user/dologin.action的參數需要加密 所以需要在<param-name>標簽內配置,
也是說可以根據自我需求在<param-name>標簽內配置需要加密的請求路徑
可以參照對比RsaDecryptRequestParamFilter.java類的doFilter方法
<!--加載RsaDecryptRequestParamFilter--> <filter> <filter-name>RSA</filter-name> <filter-class>com.lc.utils.RsaDecryptRequestParamFilter</filter-class> <init-param> <description>過濾掉不需要加密的post請求 留下需要加密的請求 如路徑:/user/dologin.action,/fuwu/doyuyue.action</description> <param-name>NeedRsaUrl</param-name> <param-value>/user/dologin.action,/fuwu/doyuyue.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() {/*form表單數據的登錄按鈕觸發事件 */ var encrypt=new JSEncrypt(); /*放入獲得的公鑰*/ encrypt.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1ktivIcFm6pmMafrOHWLW5dHpqk2qFeZJQ/XYYzrKF7rj6jv5qRr0P2ihB1iw+tlz8FKaxHPOvWTmRJzfjFsNhHyfPwHoyDPThc2LHtv7UzHVHSfUTWEH5e1xbYYkHNQEy76Y0q/oAaHf8ms1xe/Z4oq5MqIY2mENYMEpBcACuwIDAQAB"); /*放入,獲得有關用戶登錄的表單數據*/ encrypted=encrypt.encrypt($("form").serialize());
alert(encryted); $.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類 過濾時 ,doFilter方法中因容錯機制滿足(包含)要加密的請求,就會調用的RSAUtil.java類的靜態方法進行解密(密文)
即解密效果:
。。。。。。。。。
不煮米飯的電飯鍋