沐春风

导航

Java采用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

如图:

 

 

第二步:向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地址:https://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类的静态方法进行解密(密文)

即解密效果:

 

 

。。。。。。。。。

不煮米饭的电饭锅

posted on 2018-07-18 15:29  沐春秋  阅读(2246)  评论(0编辑  收藏  举报