我的项目是一些使用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。但我仍然不知道该怎么做。