Spring Boot 如何防护 XSS + SQL 注入攻击 ?一文带你搞定!


import com.green.admin.common.utils.core.StringUtils;
import com.green.admin.common.configures.SystemConfig;
import com.green.admin.core.wrappers.XssHttpServletRequestWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;

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


/**
 * 防止XSS攻击的过滤器
 */
@Order(FilterRegistrationBean.HIGHEST_PRECEDENCE)
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
@WebFilter(filterName = "xssFilter", urlPatterns = "/*")
public class XssFilter implements Filter {

    private final SystemConfig systemConfig;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;

        if (handleExcludeUrl(req)) {
            chain.doFilter(request, response);
            return;
        }

        if (systemConfig.getXssEnabled()) {
            if (handleIncludeUrl(req)) {
                XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
                chain.doFilter(xssRequest, response);
                return;
            }
        }

        chain.doFilter(request, response);
    }

    /**
     * 排除链接操作
     */
    private boolean handleExcludeUrl(HttpServletRequest request) {
        String url = request.getServletPath();
        String method = request.getMethod();

        // GET DELETE 不过滤
        if (Objects.isNull(method) || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) {
            return true;
        }

        return StringUtils.matches(url, systemConfig.getXssUrlExcludes());
    }

    /**
     * 匹配链接操作
     */
    private boolean handleIncludeUrl(HttpServletRequest request) {
        String url = request.getServletPath();

        return StringUtils.matches(url, systemConfig.getXssUrlPatterns());
    }

}

import com.green.admin.common.utils.core.StringUtils;
import com.green.admin.common.utils.html.HtmlUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

    /**
     * @param request 请求
     */
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getQueryString() {
        return HtmlUtils.clean(super.getQueryString());
    }

    @Override
    public String getParameter(String name) {
        return HtmlUtils.clean(super.getParameter(name));
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);

        if (Objects.nonNull(values)) {
            int length = values.length;
            String[] escapeValues = new String[length];

            for (int i = 0; i < length; i++) {
                // 防xss攻击和过滤前后空格
                escapeValues[i] = HtmlUtils.clean(values[i]).trim();
            }

            return escapeValues;
        }

        return super.getParameterValues(name);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        // 非json类型,直接返回
        if (!isJsonRequest()) {
            return super.getInputStream();
        }

        // 为空,直接返回
        String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);

        if (StringUtils.isEmpty(json)) {
            return super.getInputStream();
        }

        // xss过滤
        json = HtmlUtils.clean(json).trim();
        byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
        final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);

        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return true;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public int available() {
                return jsonBytes.length;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() {
                return bis.read();
            }
        };
    }

    /**
     * 是否是Json请求
     */
    public boolean isJsonRequest() {
        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
    }

}


@Getter
@Setter
@Component
@SuppressWarnings("all")
@ConfigurationProperties(prefix = "system")
@PropertySource(value = {"classpath:/config/system-config-${spring.profiles.active}.properties",
        "file:./config/config/system-config-${spring.profiles.active}.properties"}, ignoreResourceNotFound = true)
public class SystemConfig {

 /**
     * 防止XSS攻击过滤开关
     */
    private Boolean xssEnabled;

    /**
     * XSS排除链接(多个用逗号分隔)
     */
    private List xssUrlExcludes;

    /**
     * XSS匹配链接
     */
    private List xssUrlPatterns;
}

system-config-dev.properties

#防止XSS攻击过滤开关
system.xss_enabled=true

#排除链接(多个用逗号分隔)
system.xss_url_excludes=/system/notice

#匹配链接(多个用逗号分隔)
system.xss_url_patterns=/user/*

你可能感兴趣的:(Java,SpringBoot,spring,boot,xss,sql)