XSS的具体解释这里不多说,XSS简单的防注入其实就是字符的替换和屏蔽。这就需要我们在服务器接受数据对数据进行处理。
Filter能在request到达servlet的服务方法之前拦截HttpServletRequest对象,而在服务方法转移控制后又能拦截HttpServletResponse对象。
但是不能修改HttpServletRequest对象,我们可以用HttpServletRequestWrapper包装HttpServletRequest对象通过包装实现参数的修改。
这里简单介绍下ajax的请求在由HttpServletRequestWrapper拦截时获取参数的情况。
根据Servlet规范,如果同时满足下列条件,则请求体(Entity)中的表单数据,将被填充到request的parameter集合中(request.getParameter系列方法可以读取相关数据):
1 这是一个HTTP/HTTPS请求
2 请求方法是POST(querystring无论是否POST都将被设置到parameter中)
3 请求的类型(Content-Type头)是application/x-www-form-urlencoded
4 Servlet调用了getParameter系列方法
如果上述条件没有同时满足,则相关的表单数据不会被设置进request的parameter集合中,相关的数据可以通过request.getInputStream()来访问。反之,如果上述条件均满足,相关的表单数据将不能再通过request.getInputStream()来读取。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang3.StringEscapeUtils;
import com.alibaba.fastjson.JSON;
import com.fx.urthinkerManager.utils.StringUtil;
public class XSSRequestWrapper extends HttpServletRequestWrapper {
private String body;
//private Map<String, String[]> parameterMap; // 所有参数的Map集合
public XSSRequestWrapper(HttpServletRequest request) {
super(request);
body = HttpGetBody.getBodyString(request);
//parameterMap = request.getParameterMap();
}
@Override
public String getQueryString() {
return StringEscapeUtils.escapeHtml4(super.getQueryString());
}
@Override
public Object getAttribute(String name) {
return super.getAttribute(name);
}
@Override
public String getHeader(String name) {
return StringEscapeUtils.escapeHtml4(super.getHeader(name));
}
@Override
public String getParameter(String name) {
System.out.println(super.getParameter(name));
return StringEscapeUtils.escapeHtml4(super.getParameter(name));
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if(values != null) {
int length = values.length;
String[] escapseValues = new String[length];
for(int i = 0; i < length; i++){
escapseValues[i] = StringEscapeUtils.escapeHtml4(values[i]);
}
return escapseValues;
}
return super.getParameterValues(name);
}
@Override
public ServletInputStream getInputStream() throws IOException {
ServletInputStream inputStream = null;
if(StringUtil.isNotEmpty(body)){
Map<String, Object> paramMap = JSON.parseObject(body);
for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
paramMap.put(StringEscapeUtils.escapeHtml4(entry.getKey()),
StringEscapeUtils.escapeHtml4(entry.getValue().toString()));
}
body = JSON.toJSONString(paramMap);
inputStream = new PostServletInputStream(body);
}
return inputStream;
}
@Override
public BufferedReader getReader() throws IOException {
String enc = getCharacterEncoding();
if(enc == null) enc = "UTF-8";
return new BufferedReader(new InputStreamReader(getInputStream()));
}
辅助类1:由数据流过去body参数
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ServletRequest;
public class HttpGetBody {
/**
* 获取请求Body
* @param request
* @return
*/
public static String getBodyString(ServletRequest request) {
//StringBuilder sb = new StringBuilder();
StringBuffer sb = new StringBuffer();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
辅助类2:包装数据流,用于后续的controller 获取参数
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import javax.servlet.ServletInputStream;
public class PostServletInputStream extends ServletInputStream {
private InputStream inputStream;
private String body ;//解析json之后的文本
public PostServletInputStream(String body) throws IOException {
this.body=body;
inputStream = null;
}
private InputStream acquireInputStream() throws IOException {
if(inputStream == null) {
inputStream = new ByteArrayInputStream(body.getBytes(Charset.forName("UTF-8")));
//通过解析之后传入的文本生成inputStream以便后面control调用
}
return inputStream;
}
public void close() throws IOException {
try {
if(inputStream != null) {
inputStream.close();
}
}
catch(IOException e) {
throw e;
}
finally {
inputStream = null;
}
}
public boolean markSupported() {
return false;
}
public synchronized void mark(int i) {
throw new UnsupportedOperationException("mark not supported");
}
public synchronized void reset() throws IOException {
throw new IOException(new UnsupportedOperationException("reset not supported"));
}
@Override
public int read() throws IOException {
return acquireInputStream().read();
}
}
filter
import java.io.IOException;
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 com.fx.urthinkerManager.XSSRequest.XSSRequestWrapper;
public class XSSpringFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
chain.doFilter(new XSSRequestWrapper(req), response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
在web.xml配置
<filter>
<filter-name>XSSFilter</filter-name>
<filter-class>com.123.XSSpringFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XSSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
好了,代码贴完了。
我也不知道自己写了个啥。。