zoukankan      html  css  js  c++  java
  • 【快学SpringBoot】过滤XSS脚本攻击(包括json格式)

    若图片查看异常,请前往掘金查看:https://juejin.im/post/5d079e555188251ad81a28d9

    XSS攻击是什么

    XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。

    简而言之,就是作恶用户通过表单提交一些前端代码,如果不做处理的话,这些前端代码将会在展示的时候被浏览器执行。

    如何避免XSS攻击

    解决XSS攻击,可以通过后端对输入的数据做过滤或者转义,使XSS攻击代码失效。

    代码实现

    对于过滤XSS脚本的代码,通过搜索引擎可以搜索到很多,但似乎都不是那么全面。基本上都是只能过滤querystring(表单类型)类型的入参,而不能过滤json类型的入参。其实,在现在的开发中,更多的是使用json类型做数据交互。下面就直接贴代码了:

    新建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的方法。大家可以通过打印一个输出来验证一下。

    StringEscapeUtils.escapeHtml4这个方法来自Apache的工具类,maven坐标如下:

    <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方法,通过重写该方法打印输出可以证明)。

    测试

    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】15、SpringBoot过滤XSS脚本攻击

    【快学springboot】15、SpringBoot过滤XSS脚本攻击

    【快学springboot】15、SpringBoot过滤XSS脚本攻击

    可以看到,js代码已经经过转义。转义过后的代码,即使前端读取过去了,也不会被浏览器执行的。

  • 相关阅读:
    ofbiz定时任务配置
    MySQL重置root密码
    谷歌默认最小字体解决方案
    CSS样式-文字在一行内显示不换行,超出部分用省略号(white-space、overflow、text-overflow、word-wrap、word-break)
    使用gulp自动化打包合并前端静态资源(CSS、JS文件压缩、添加版本号)
    JS判断两个日期是否为同一周
    AES、DES加解密方法(Java和JS编程)
    Nodejs代理解决开发环境下跨域问题
    js的垃圾收集机制以及写代码如何处理
    手机端黑屏时定时器无法执行
  • 原文地址:https://www.cnblogs.com/happy4java/p/11205862.html
Copyright © 2011-2022 走看看