java防止html脚本注入
html脚本注入就是跨站脚本攻击(XSS),指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。
在前端输入一些内容,提交到服务器后直接原样返回,然后再append到一个div中显示:
<form id="f1"> Name:<input type="text" name="name"/> <input type="button" value="submit"/> </form> <div id="content"></div> <script src="js/jquery-1.12.4.min.js"></script> <script> $(function(){ $(':button').on('click', function(){ var param = $('#f1').serialize(); $.ajax({ url : 'add', type : 'post', data : param, success : function(result){ console.log(result); $('#content').append(result + '<br>'); } }); }); }) </script>
@RestController public class TestController { @PostMapping("/add") public String add(String name){ System.out.println(name); return name; } }
如果在运行后输入一串html脚本代码,运行如下:
在控制台输出内容:
<a href="#">hello<a>
这里就来解决html脚本注入问题:
这里的解决思路就是定义一个拦截器,拦截所有请求,因为请求的所有表单数据都存放在HttpServletRequest对象中,所以只需要拿到这个对象并对原有的方法进行增强即可。
导包:
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.3.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-text</artifactId> <version>1.6</version> </dependency> </dependencies>
public class XssRequestWrapper extends HttpServletRequestWrapper { public XssRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getHeader(String name) { String value = super.getHeader(name); return StringEscapeUtils.escapeHtml4(value); } @Override public String getParameter(String name) { //获取页面数据 String value = super.getParameter(name); //进行字符转义 System.out.println("转义后的字符:" + StringEscapeUtils.escapeHtml4(value)); return StringEscapeUtils.escapeHtml4(value); } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); if(values != null){ String[] escValues = new String[values.length]; for (int i=0; i<values.length; i++) { escValues[i] = StringEscapeUtils.escapeHtml4(values[i]); } return escValues; } return super.getParameterValues(name); } }
定义一个过滤器,拦截所有请求:
@WebFilter(urlPatterns = "/*") public class XssFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; //实例化自定义的RequestWrapper对象 XssRequestWrapper requestWrapper = new XssRequestWrapper(request); //放行,HttpServletRequest最终也是实现了ServletRequest,所以放行可以传requestWrapper对象 filterChain.doFilter(requestWrapper, servletResponse); } }
运行结果:
控制台输出:
<a href="#">hello<a>