Spring boot 설정 XSS 방어 필터
9920 단어 Java
프레임:앞 뒤 분리,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 이 민감 한 문 자 를 입력 하면 안전 문자 로 전환 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.