【快學SpringBoot】過濾XSS腳本攻擊(包括json格式)

XSS攻擊是什麼

XSS攻擊全稱跨站腳本攻擊,是爲不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫爲XSS,XSS是一種在web應用中的計算機安全漏洞,它容許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。前端

簡而言之,就是做惡用戶經過表單提交一些前端代碼,若是不作處理的話,這些前端代碼將會在展現的時候被瀏覽器執行。java

如何避免XSS攻擊

解決XSS攻擊,能夠經過後端對輸入的數據作過濾或者轉義,使XSS攻擊代碼失效。web

代碼實現

對於過濾XSS腳本的代碼,經過搜索引擎能夠搜索到不少,但彷佛都不是那麼全面。基本上都是隻能過濾querystring(表單類型)類型的入參,而不能過濾json類型的入參。其實,在如今的開發中,更多的是使用json類型作數據交互。下面就直接貼代碼了:spring

新建XssAndSqlHttpServletRequestWrapper.java

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
 * @author Happy
 * 防止XSS攻擊
 */
public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {
 private HttpServletRequest request;
 public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {
 super(request);
 this.request = request;
 }
 @Override
 public String getParameter(String name) {
 String value = request.getParameter(name);
 if (!StringUtils.isEmpty(value)) {
 value = StringEscapeUtils.escapeHtml4(value);
 }
 return value;
 }
 @Override
 public String[] getParameterValues(String name) {
 String[] parameterValues = super.getParameterValues(name);
 if (parameterValues == null) {
 return null;
 }
 for (int i = 0; i < parameterValues.length; i++) {
 String value = parameterValues[i];
 parameterValues[i] = StringEscapeUtils.escapeHtml4(value);
 }
 return parameterValues;
 }
}
複製代碼

這裏重寫了兩個方法:getParameter和getParameterValues,getParameter方法是直接經過request得到querystring類型的入參調用的方法。若是是經過springMVC註解類型來得到參數的話,走的是getParameterValues的方法。你們能夠經過打印一個輸出來驗證一下。apache

StringEscapeUtils.escapeHtml4這個方法來自Apache的工具類,maven座標以下:json

<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-text</artifactId>
 <version>1.4</version>
</dependency>
複製代碼

新建XssFilter.java

過濾的代碼寫完了,下面就是在一個filter中應用該代碼。後端

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
 * @author Happy
 */
@WebFilter
@Component
public class XssFilter implements Filter {
 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
 }
 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
 throws IOException, ServletException {
 HttpServletRequest req = (HttpServletRequest) request;
 XssAndSqlHttpServletRequestWrapper xssRequestWrapper = new XssAndSqlHttpServletRequestWrapper(req);
 chain.doFilter(xssRequestWrapper, response);
 }
 @Override
 public void destroy() {
 }
 /**
 * 過濾json類型的
 * @param builder
 * @return
 */
 @Bean
 @Primary
 public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) {
 //解析器
 ObjectMapper objectMapper = builder.createXmlMapper(false).build();
 //註冊xss解析器
 SimpleModule xssModule = new SimpleModule("XssStringJsonSerializer");
 xssModule.addSerializer(new XssStringJsonSerializer());
 objectMapper.registerModule(xssModule);
 //返回
 return objectMapper;
 }
}
複製代碼

過濾表單類型的代碼已經完成(xssObjectMapper這個是後面過濾json類型纔用到的)。下面來實現過濾json類型的代碼:瀏覽器

新建XssStringJsonSerializer.java

代碼以下:安全

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.text.StringEscapeUtils;
import java.io.IOException;
public class XssStringJsonSerializer extends JsonSerializer<String> {
 @Override
 public Class<String> handledType() {
 return String.class;
 }
 @Override
 public void serialize(String value, JsonGenerator jsonGenerator,
 SerializerProvider serializerProvider) throws IOException {
 if (value != null) {
 String encodedValue = StringEscapeUtils.escapeHtml4(value);
 jsonGenerator.writeString(encodedValue);
 }
 }
}
複製代碼

這裏是經過修改SpringMVC的json序列化來達到過濾xss的目的的。其實也能夠經過第一種方法,重寫getInputStream方法來實現,這裏我就不作演示了(經過json類型傳參會走getInputStream方法,經過重寫該方法打印輸出能夠證實)。springboot

測試

TestController.java

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
 * @author Happy
 */
@RestController
@RequestMapping(value = "/test")
public class TestController {
 @PostMapping(value = "/xss")
 public Object test(String name) {
 System.out.println(name);
 return name;
 }
 @PostMapping(value = "/json")
 public Object testJSON(@RequestBody Param param) {
 return param;
 }
 @GetMapping(value = "/query")
 public Object testQuery(String q){
 return q;
 }
 @PostMapping(value = "/upload")
 public Object upload(MultipartFile file){
 System.out.println(file.getOriginalFilename());
 return "OK";
 }
}
複製代碼

下面經過postman測試下效果:

【快學springboot】1五、SpringBoot過濾XSS腳本攻擊

【快學springboot】1五、SpringBoot過濾XSS腳本攻擊

【快學springboot】1五、SpringBoot過濾XSS腳本攻擊

能夠看到,js代碼已經通過轉義。轉義事後的代碼,即便前端讀取過去了,也不會被瀏覽器執行的。

相關文章
相關標籤/搜索