Filter转义后的特殊字符,如果需要直接使用可以通过 XssFilter.XssHttpServletRequestWrapper.unescapeHtml(value)还原,入库和传给前端用转义后的字符串,前端自行还原
package com.suyun.common.filters;
import com.suyun.common.utils.Encodes;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Description:
* <p>
* URL和参数转义Filter
* </p>
*
* @Author: leo.xiong
* @CreateDate: 2022/9/8 9:04
* @Email: leo.xiong@suyun360.com
* @Since:
*/
@WebFilter(urlPatterns = "/*", filterName = "xssFilter")
public class XssFilter implements Filter {
private static final Pattern ILLEGAL_ONE_PATTERN = Pattern.compile("--><script>.*</script><!--");
private static final Pattern ILLEGAL_TWO_PATTERN = Pattern.compile("<script>.*</script>");
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
//参数转义
HttpServletRequest wrapper = new XssHttpServletRequestWrapper((HttpServletRequest) request);
String url = wrapper.getRequestURL().toString();
if (StringUtils.isEmpty(url)) {
chain.doFilter(wrapper, response);
return;
}
String newUrl = replace(url, ILLEGAL_ONE_PATTERN);
if (url.equals(newUrl)) {
chain.doFilter(wrapper, response);
return;
}
//URL转义
wrapper.getRequestDispatcher(newUrl).forward(wrapper, response);
return;
}
chain.doFilter(request, response);
}
private String replace(String url, Pattern pattern) {
Matcher match = pattern.matcher(url);
if (match.find()) {
String value = match.group(0);
try {
url = url.replace(value, URLEncoder.encode(value, StandardCharsets.UTF_8.name()));
replace(url, pattern);
} catch (UnsupportedEncodingException e) {
}
} else {
return url;
}
return replace(url, ILLEGAL_TWO_PATTERN);
}
@Override
public void destroy() {
}
/**
* 防范XSS攻击
*/
public static class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
}
/**
* 使用参数时调用的方法,会把参数转义
*
* @param parameter
* @return
*/
@Override
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = Encodes.escapeHtml(values[i]);
}
return encodedValues;
}
/**
* 使用参数时调用的方法,会把参数转义
*
* @param parameter
* @return
*/
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return Encodes.escapeHtml(value);
}
/**
* 使用参数时调用的方法,会把参数转义
*
* @param name
* @return
*/
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if (value == null) {
return null;
}
return Encodes.escapeHtml(value);
}
/**
* 还原
* @param value
* @return
*/
public static final String unescapeHtml(String value) {
return StringEscapeUtils.unescapeXml(Encodes.unescapeHtml(value));
}
}
}
package com.suyun.common.utils;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* Description:
* <p>
* * 封装各种格式的编码解码工具类.
* * 1.Commons-Codec的 hex/base64 编码
* * 2.自制的base62 编码
* * 3.Commons-Lang的xml/html escape
* * 4.JDK提供的URLEncoder
* </p>
*
* @Author: leo.xiong
* @CreateDate: 2022/9/9 15:14
* @Email: leo.xiong@suyun360.com
* @Since:
*/
public class Encodes {
private static final String DEFAULT_URL_ENCODING = "UTF-8";
private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
/**
* Hex编码.
*/
public static String encodeHex(byte[] input) {
return new String(Hex.encodeHex(input));
}
/**
* Hex解码.
*/
public static byte[] decodeHex(String input) {
try {
return Hex.decodeHex(input.toCharArray());
} catch (DecoderException e) {
throw Exceptions.unchecked(e);
}
}
/**
* Base64编码.
*/
public static String encodeBase64(byte[] input) {
return new String(Base64.encodeBase64(input));
}
/**
* Base64编码.
*/
public static String encodeBase64(String input) {
try {
return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING)));
} catch (UnsupportedEncodingException e) {
return "";
}
}
// /**
// * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
// */
// public static String encodeUrlSafeBase64(byte[] input) {
// return Base64.encodeBase64URLSafe(input);
// }
/**
* Base64解码.
*/
public static byte[] decodeBase64(String input) {
return Base64.decodeBase64(input.getBytes());
}
/**
* Base64解码.
*/
public static String decodeBase64String(String input) {
try {
return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* Base62编码。
*/
public static String encodeBase62(byte[] input) {
char[] chars = new char[input.length];
for (int i = 0; i < input.length; i++) {
chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
}
return new String(chars);
}
/**
* Html 转码.
*/
public static String escapeHtml(String html) {
return StringEscapeUtils.escapeHtml4(html);
}
/**
* Html 解码.
*/
public static String unescapeHtml(String htmlEscaped) {
return StringEscapeUtils.unescapeHtml4(htmlEscaped);
}
/**
* Xml 转码.
*/
public static String escapeXml(String xml) {
return StringEscapeUtils.escapeXml10(xml);
}
/**
* Xml 解码.
*/
public static String unescapeXml(String xmlEscaped) {
return StringEscapeUtils.unescapeXml(xmlEscaped);
}
/**
* URL 编码, Encode默认为UTF-8.
*/
public static String urlEncode(String part) {
try {
return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
throw Exceptions.unchecked(e);
}
}
/**
* URL 解码, Encode默认为UTF-8.
*/
public static String urlDecode(String part) {
try {
return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
throw Exceptions.unchecked(e);
}
}
}
public static void main(String[] args) throws UnsupportedEncodingException {
String value = "{\"张三\":\"12\",\"李四\":\"<script>alert(1)</script>\"}";
//转义
String escape = StringEscapeUtils.escapeHtml(value);
System.out.println(escape);
//还原
String unescape = XssFilter.XssHttpServletRequestWrapper.unescapeHtml(escape);
System.out.println(unescape);
}

版权声明:本文为xionglangs原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。