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>