Spring boot 설정 XSS 방어 필터

9920 단어 Java
백 엔 드 인 터 페 이 스 는 XSS 공격 방 어 를 해 야 합 니 다.인터넷 에서 찾 아 보면 방어 방식 이 많 습 니 다.XSS 공격 이 무엇 인지 에 대해 온라인 에서 도 설명 이 많다.이 블 로 그 는 자신의 프로젝트 에 대해 기록 을 해 야 한다.
프레임:앞 뒤 분리,Spring Boot
장면:백 엔 드 인터페이스 파라미터 가 일정 하지 않 고@RequestBody 형식 으로 수신 되 며@RequestParam 형식 으로 수신 되 기 때문에 서로 다른 처리 가 있 습 니 다.
아래 에 코드 붙 이기:
필터:
public class XssFilter implements Filter {

    @Override
    public void init(FilterConfig config) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request);
        chain.doFilter(xssHttpServletRequestWrapper, response);
    }

    @Override
    public void destroy() {}
}

민감 문자 변환 클래스:
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    HttpServletRequest orgRequest = null;

    private String body;

    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        orgRequest = request;
        body = HttpGetBody.getBodyString(request);
    }

    /**
     *   getParameter  ,          xss  。
* , super.getParameterValues(name)
* getParameterNames,getParameterValues getParameterMap */ @Override public String getParameter(String name) { String value = super.getParameter(xssEncode(name, 0)); if (null != value) { value = xssEncode(value, 0); } return value; } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(xssEncode(name, 0)); if (values == null) { return null; } int count = values.length; String[] encodedValues = new String[count]; for (int i = 0; i < count; i++) { encodedValues[i] = xssEncode(values[i], 0); } return encodedValues; } @Override public Map getParameterMap() { HashMap paramMap = (HashMap) super.getParameterMap(); paramMap = (HashMap) paramMap.clone(); for (Iterator iterator = paramMap.entrySet().iterator(); iterator.hasNext(); ) { Map.Entry entry = (Map.Entry) iterator.next(); String[] values = (String[]) entry.getValue(); for (int i = 0; i < values.length; i++) { if (values[i] instanceof String) { values[i] = xssEncode(values[i], 0); } } entry.setValue(values); } return paramMap; } @Override public ServletInputStream getInputStream() throws IOException { ServletInputStream inputStream = null; if (StringUtil.isNotEmpty(body)) { body = xssEncode(body, 1); inputStream = new TranslateServletInputStream(body); } return inputStream; } /** * getHeader , xss 。
* , super.getHeaders(name)
* getHeaderNames */ @Override public String getHeader(String name) { String value = super.getHeader(xssEncode(name, 0)); if (value != null) { value = xssEncode(value, 0); } return value; } /** * xss * * @param s * @return */ private static String xssEncode(String s, int type) { if (s == null || s.isEmpty()) { return s; } StringBuilder sb = new StringBuilder(s.length() + 16); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (type == 0) { switch (c) { case '\'': // sb.append('‘'); break; case '\"': // sb.append('“'); break; case '>': // sb.append('>'); break; case '': // sb.append('>'); break; case '= index + 2) { // %3c, %3C if (s.charAt(index + 1) == '3' && (s.charAt(index + 2) == 'c' || s.charAt(index + 2) == 'C')) { sb.append('<'); return; } // %3c (0x3c=60) if (s.charAt(index + 1) == '6' && s.charAt(index + 2) == '0') { sb.append('<'); return; } // %3e, %3E if (s.charAt(index + 1) == '3' && (s.charAt(index + 2) == 'e' || s.charAt(index + 2) == 'E')) { sb.append('>'); return; } // %3e (0x3e=62) if (s.charAt(index + 1) == '6' && s.charAt(index + 2) == '2') { sb.append('>'); return; } } sb.append(s.charAt(index)); } /** * request * * @return */ public HttpServletRequest getOrgRequest() { return orgRequest; } /** * request * * @return */ public static HttpServletRequest getOrgRequest(HttpServletRequest req) { if (req instanceof XssHttpServletRequestWrapper) { return ((XssHttpServletRequestWrapper) req).getOrgRequest(); } return req; } }

설정 클래스:
@Configuration
public class XSSFilterConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(xssFilter());
        registration.addUrlPatterns("/*");
        registration.addInitParameter("paramName", "paramValue");
        registration.setName("xssFilter");
        return registration;
    }

    /**
     *     bean
     * @return
     */
    @Bean(name = "xssFilter")
    public Filter xssFilter() {
        return new XssFilter();
    }
}

두 도구 종류의 코드 를 추가 합 니 다:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;


public class TranslateServletInputStream extends ServletInputStream {
    private InputStream inputStream;
    /**
     *   json     
     */
    private String body;

    public TranslateServletInputStream(String body) throws IOException {
        this.body = body;
        inputStream = null;
    }

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

    @Override
    public void setReadListener(ReadListener readListener) {

    }

    @Override
    public boolean isFinished() {
        return false;
    }

    private InputStream acquireInputStream() throws IOException {
        if (inputStream == null) {
            inputStream = new ByteArrayInputStream(body.getBytes(Charset.forName("UTF-8")));
            //             inputStream    controller  
        }

        return inputStream;
    }

    @Override
    public void close() throws IOException {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (IOException e) {
            throw e;
        } finally {
            inputStream = null;
        }
    }

    @Override
    public boolean markSupported() {
        return false;
    }

    @Override
    public synchronized void mark(int i) {
        throw new UnsupportedOperationException("mark not supported");
    }

    @Override
    public synchronized void reset() throws IOException {
        throw new IOException(new UnsupportedOperationException("reset not supported"));
    }

    @Override
    public int read() throws IOException {
        return acquireInputStream().read();

    }

}
import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;


public class HttpGetBody {

    /**
     *     Body
     * @param request
     * @return
     */
    public static String getBodyString(ServletRequest request) {
        StringBuffer sb = new StringBuffer();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
}

상기 코드 에서 보 듯 이 테스트 는 매개 변수 나 url 이 민감 한 문 자 를 입력 하면 안전 문자 로 전환 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기