XSS简介:
XSS(Cross Site Scripting)
,跨站脚本攻击,是一种允许攻击者在另外一个用户的浏览器中执行恶意代码脚本的脚本注入式攻击。本来缩小应该是CSS
,但为了和层叠样式(Cascading Style Sheet,CSS)
有所区分,故称XSS
。
简单的说就是在互联网的环境下,用户进行新增操作时,输入了类似<script>alert(0)</script>的脚本语言。会导致程序在解析这种脚本语言时发生乱套的情况。
解决方式一:通过前端代码解决
解析用户输入的数据,将一些<script>等特殊字符进行转码操作,等到需要显示的时候再把数据进行html解码操作,转码和解码的方法如下所示,ajax提交时,提交的参数格式为HtmlUtil.htmlEncode(参数值)。界面返回赋值的参数格式为HtmlUtil.htmlDecode(参数值)。
需要注意的是,在查询界面需要将查询框的参数也要进行转码操作,因为数据库存的是转码的格式,要统一。
var HtmlUtil = {
/*1.用浏览器内部转换器实现html转码*/
htmlEncode : function(html) {
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement("div");
//2.然后将要转换的字符串设置为这个元素的innerText(ie支持)或者textContent(火狐,google支持)
(temp.textContent != undefined) ? (temp.textContent = html)
: (temp.innerText = html);
//3.最后返回这个元素的innerHTML,即得到经过HTML编码转换的字符串了
var output = temp.innerHTML;
temp = null;
return output;
},
/*2.用浏览器内部转换器实现html解码*/
htmlDecode : function(text) {
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement("div");
//2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)
temp.innerHTML = text;
//3.最后返回这个元素的innerText(ie支持)或者textContent(火狐,google支持),即得到经过HTML解码的字符串了。
var output = temp.innerText || temp.textContent;
temp = null;
return output;
}
};
现在的效果,在table表格浏览器可以正常显示名字,但是在输入框内也可以正常显示名字,但是有时候下拉菜单会出现转义后的名称。
缺点就是,若界面比较多,需要改的地方就比较多。
解决方式二:通过后端代码解决
和前端解决的方式类似,配置一个过滤器,将一些特殊字符进行转码操作后再存储到数据库中,若用户输入的是<script>alert(0)</script>,那么数据库存储的就是 <script>alert(1)</script>
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang3.StringEscapeUtils;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getHeader(String name) {
return StringEscapeUtils.escapeHtml4(super.getHeader(name));
}
@Override
public String getQueryString() {
return StringEscapeUtils.escapeHtml4(super.getQueryString());
}
@Override
public String getParameter(String 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);
}
}
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 org.springframework.context.annotation.Configuration;
@Configuration
public class XssFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
filterChain.doFilter(new XssHttpServletRequestWrapper(request),servletResponse);
}
@Override
public void destroy() {
}
}
现在的效果,在table表格浏览器可以正常显示名字,但是在输入框内就无法正常显示名字了,这个属于正常现象