1. 程式人生 > >Maven項目的RSA加密及解密(用戶數據)的配置流程:

Maven項目的RSA加密及解密(用戶數據)的配置流程:

nts iic params replace irf contains czc mapping cte

  做過三年多的程序員了,之前同事們都喜歡發表博客文章 而鄙人特例。 一般都是看文章,畢竟有現成的糧食,幹嘛還多此一舉額,呵呵。

  也就沒想著註冊一下賬號 就在前不久註冊這個賬號了 也是沒怎更好的利用起來 ; 這不心血來潮 ,突然意識到不發表些博客文章 感覺就不是一個完整的程序員 ,因此就有了以下文章 。

  頭一次發表 若有人查閱 如有什不足之處,多提意見, 多多見諒。。。

第一步:

獲得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> 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());
          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類 過濾 ,因容錯機制不匹配後,被調用的RSAUtil.java類 解密 密文

即解密效果:

技術分享圖片

。。。。。。

不煮米飯的電飯鍋

Maven項目的RSA加密及解密(用戶數據)的配置流程: