如何使用springMVC Web Project中的过滤器加密/解密数据?

时间:2017-10-18 10:00:55

标签: spring-mvc servlets encryption filter

我的项目是一些使用Spring + SpringMVC + Mybaits框架的java web项目。这是一个加密一些数据的要求,如用户名,mobile,数据库中的identify_number和post需求。我在数据库中加密这些列。我添加在一个名为mobile-project的项目中有两个过滤器,它为其他人提供post服务。在filter的doFilter()方法中,我用我的encryptRequestWrapper替换了servletRequest,它扩展了HttpServletRequestWrapper.I覆盖了它的getParameter()方法并加密了一些数据在这种方法中。它运行良好,数据已经加密/解密。 现在我把它复制到其他项目,它没有用。这是我的过滤器代码:

package com.xinrong.web.admin.security;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

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;

public class RequestEncryptFilter implements Filter {
    private Set<String> prefixUrls = new HashSet<String>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String contextPath = filterConfig.getServletContext().getContextPath();
        String ignoreStr = filterConfig.getInitParameter("ignoreReqPrefix");
        String[] ignorePatterns = ignoreStr.split(",");
        for (String prefix : ignorePatterns) {
            prefixUrls.add(contextPath + prefix);
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        if (!isIgnoreUrl(req)) {
            String requestType = (String) req.getHeader("X-Requested-With");
            if (requestType != null && requestType.equals("XMLHttpRequest")) {
                chain.doFilter(new RequestBodyEncryptWrapper(req), response);
            } else {
                chain.doFilter(new RequestEncryptWapper(req), response);
            }
            chain.doFilter(new RequestEncryptWapper(req), response);
        } else {
            chain.doFilter(request, response);
        }

    }

    @Override
    public void destroy() {
        prefixUrls = null;
    }

    private boolean isIgnoreUrl(HttpServletRequest request) {
        String url = request.getRequestURI();
        for (String prefix : prefixUrls) {
            if (url.startsWith(prefix)) {
                return true;
            }
        }
        return false;
    }

}




package com.xinrong.web.admin.security;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang3.ArrayUtils;

import com.xinrong.service.bank.rongbao.pay.AES;
import com.xinrong.utils.UrlUtil;

public class RequestBodyEncryptWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    public RequestBodyEncryptWrapper(HttpServletRequest request)
            throws IOException {
        super(request);
        ServletInputStream stream = request.getInputStream();
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = stream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        this.body = swapStream.toByteArray();
        String tmpStr=new String(body,"UTF-8");
        System.out.println("request tmp str:"+tmpStr);
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    @Override
    public String getParameter(String name) {
        String queryUrl = getRequestPayload();
        return UrlUtil.getEncryptPara(queryUrl, name);
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] vals=super.getParameterValues(name);
        if(ArrayUtils.contains(UrlUtil.encryptKeyArr, name)){
            vals[0]=AES.encryptToBase64(vals[0]);
        }
        return vals;
    }

    private String getRequestPayload() {
        StringBuilder sb = new StringBuilder();
        try {
            BufferedReader reader = getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}


package com.xinrong.web.admin.security;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Logger;

import com.xinrong.service.bank.rongbao.pay.AES;
import com.xinrong.utils.UrlUtil;

public class RequestEncryptWapper extends HttpServletRequestWrapper {

    public RequestEncryptWapper(HttpServletRequest request) {
        super(request);
    }

    private Logger logger = Logger.getLogger(RequestEncryptWapper.class);

    @Override
    public String[] getParameterValues(String name) {
        String[] strs = super.getParameterValues(name);
        if (strs == null || strs.length == 0) {
            return strs;
        }
        if (ArrayUtils.contains(UrlUtil.encryptKeyArr, name)) {
            logger.info("before encrypt:" + strs[0]);
            strs[0] = AES.encryptToBase64(strs[0]);
            logger.info("after encrypt:stri is:" + strs[0]);
        }
        return strs;
    }

}

这是web.xml配置。

<filter>
        <filter-name>encryptRequestFilter</filter-name>
        <filter-class>com.xinrong.web.admin.security.RequestEncryptFilter</filter-class>
        <init-param>
            <param-name>ignoreReqPrefix</param-name>
            <param-value>/statics,/main,/login,/investor/getUnAuthStatusPage</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encryptRequestFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

问题是当我在此页面中输入“12345678912”作为移动值条件时,investorVO的移动属性的值为null, queryPage

控制器方法中的

代码:

  * @param
     * @param
     * @param session
     * @return
     * @throws
     */
    @RequestMapping(value = "dataGrid")
    @ResponseBody
    public EasyuiDataGrid dataGrid(InvestorVO investorVO, HttpSession session) {
        return investorService.query(investorVO);
    }

但是如果我对过滤器无效,那么investorVO的移动属性的值就会变成“12345678912”。我猜SpringMVC中的某些内容会导致这种情况,但我不知道具体原因。

- 编辑

SpringMVC的版本是3.2.8,它不支持@requestBodyAdvice @responseBodyAdvice。

这是web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>backend</display-name>

    <!-- 设置Spring容器加载配置文件路径 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/spring.xml</param-value>
    </context-param>
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:/log4j.properties</param-value>
    </context-param>
    <!-- 解决工程编码过滤器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

    <!-- added LiYongjie encrypt -->
    <filter>
        <filter-name>encryptRequestFilter</filter-name>
        <filter-class>com.xinrong.web.admin.security.RequestEncryptFilter</filter-class>
        <init-param>
            <param-name>ignoreReqPrefix</param-name>
            <param-value>/statics,/main,/login,/investor/getUnAuthStatusPage</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encryptRequestFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

    <!-- Spring Security配置 -->
    <listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>

    <!-- SpringSecurity 核心过滤器配置 -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <!-- <filter> <filter-name>decryptResponseFilter</filter-name> <filter-class>com.xinrong.web.admin.security.ResponseDecryptFilter</filter-class> 
        <init-param> <param-name>ignoreResPrefix</param-name> <param-value>/statics,/main,/login,/investor/getUnAuthStatusPage</param-value> 
        </init-param> </filter> <filter-mapping> <filter-name>decryptResponseFilter</filter-name> 
        <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> 
        </filter-mapping> -->
    <!-- 加载Spring容器配置 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 加载Log4j配置 -->
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <!-- 加载防止内存溢出监听器 -->
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <!-- 扩展Request作用域 scope="request" 分别是 singleton、prototype、request、session、global 
        session -->
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <!-- Spring MVC Servlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:/config/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--超时 -->
    <session-config>
        <session-timeout>600</session-timeout>
    </session-config>

</web-app>

也许我知道现在的原因.SpringMVC包装请求从请求到pojo Objects.Methods getInputStream(),getReader(),getParameter()只能被请求调用一次。我在RequestBodyEncryptWrapper类中调用getInputStream(),所以当SpringMVC尝试从请求获取getParameter时,它变为null。但我仍然不知道该怎么做。

0 个答案:

没有答案
相关问题