XSS安全漏洞?使用过滤器解决前端JS注入问题。

使用过滤器解决前端XSS安全问题,JS注入问题

使用过滤器解决前端 XSS 安全问题

在Java web 项目中,对于前端 JS 注入问题,可以在前端写 JS 代码进行预处理,但是这样处理无法保证万无一失,当用户篡改前端校验的 JS 代码,导致校验失效,那么未经处理的 JS 代码保存到数据库后再次查询展示到页面,依然会出现 JS 安全问题,这时候就需要在后台做 JS 代码校验和处理。我们可以使用过滤器(Filter)处理。

过滤器

过滤器可以对目标 web 资源的请求和响应进行拦截,并做一些特定处理。
在spring boot中,针对 JS 注入问题,我们可以创建一个拦截器,文件名:XssJsonFilter

package com.qtong.afin.module.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author duchong
 * @version 1.0
 * @date 2020/9/23 12:16
 */
@WebFilter(filterName="XssJsonFilter",urlPatterns={
    
    "/workOrder/*","/Product/addProduct","/ProType/addProType/*"})
@Slf4j
public class XssJsonFilter 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;
    }
}

urlPatterns后面是需要拦截的路径,有以下几种形式:

  1. 以指定资源匹配,多资源用 , 隔开。 例如:"/Product/addProduct","/index.jsp"。
  2. 以目录匹配,多资源用 , 隔开。 例如:/Product/
  3. 以后缀名匹配,多资源用 , 隔开。例如:*.jsp
  4. 通配符,拦截所有资源。/*

这里有一个点我们需要注意: 在拦截器 XssJsonFilter 中,我们并没有使用 @Component 注解, 因为该注解会导致拦截器拦截所有的请求,这并不符合我们的预期,在实际开发中,我们可能只需要拦截部分请求,比如对于用户的查询请求、数据保存请求等,我们对于这些特定请求做统一处理即可,所以使用 @WebFilter 注解,在该注解上声明拦截路径。增加 @Component 注解后,会导致自定义的拦截路径失效,从而导致拦截用户的所有请求。

为什么使用 @Component 注解后会出现这种情况?

这是由于Spring的配置加载顺序导致的,Spring 会优先扫描加载 @Webfilter 注解,再加载 @Componet 注解 ,由于 @Componet 默认是全路径,所以会覆盖 @Webfilter 注解的匹配路径。

还需要两个类,用于拦截后的逻辑处理,分别是 XssAndSqlHttpServletRequestWrapperXssStringJsonSerializer

package com.qtong.afin.module.filter;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

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;
    }
}


package com.qtong.afin.module.filter;

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;
/**
 * @author duchong
 * @version 1.0
 * @date 2020/9/24 11:08
 */
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);
        }
    }
}

注意:

上述过滤器中,实际上是使用 StringEscapeUtils.escapeHtml4(value); 方法对一些常见的攻击性JS代码进行了转义,在使用过滤器后,前端页面就无需再写预处理的 JS 校验代码,否则可能会出现二次转义导致数据错误。

猜你喜欢

转载自blog.csdn.net/weixin_36908494/article/details/108981757