Java Filter过滤xss注入非法参数的方法
2017-01-17 10:07
489 查看
http://blog.csdn.net/feng_an_qi/article/details/45666813
Java Filter过滤xss注入非法参数的方法
web.xml:
[html] view
plain copy
<filter>
<filter-name>XSSFiler</filter-name>
<filter-class>
com.paic.mall.web.filter.XssSecurityFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.screen</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.shtml</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<servlet-name>dispatcher</servlet-name>
</filter-mapping>
XssSecurityFilter.Java
[java] view
plain copy
public class XssSecurityFilter implements Filter {
protected final Logger log = Logger.getLogger(this.getClass());
public void init(FilterConfig config) throws ServletException {
if(log.isInfoEnabled()){
log.info("XSSSecurityFilter Initializing ");
}
}
/**
* 销毁操作
*/
public void destroy() {
if(log.isInfoEnabled()){
log.info("XSSSecurityFilter destroy() end");
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest)request;
XssHttpRequestWrapper xssRequest = new XssHttpRequestWrapper(httpRequest);
httpRequest = XssSecurityManager.wrapRequest(xssRequest);
chain.doFilter(xssRequest, response);
}
}
XssHttpRequestWrapper.java
[java] view
plain copy
/**
* @author
* @date
* @describe 主要是对参数进行xss过滤,替换原始的request的getParameter相关功能
* 线程不安全
*
*/
public class XssHttpRequestWrapper extends HttpServletRequestWrapper {
protected Map parameters;
/**
* 封装http请求
*
* @param request
*/
public XssHttpRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public void setCharacterEncoding(String enc)
throws UnsupportedEncodingException {
super.setCharacterEncoding(enc);
//当编码重新设置时,重新加载重新过滤缓存。
refiltParams();
}
void refiltParams(){
parameters=null;
}
@Override
public String getParameter(String string) {
String strList[] = getParameterValues(string);
if (strList != null && strList.length > 0)
return strList[0];
else
return null;
}
@Override
public String[] getParameterValues(String string) {
if (parameters == null) {
paramXssFilter();
}
return (String[]) parameters.get(string);
}
@Override
public Map getParameterMap() {
if (parameters == null) {
paramXssFilter();
}
return parameters;
}
/**
*
* 校验参数,若含xss漏洞的字符,进行替换
*/
private void paramXssFilter() {
parameters = getRequest().getParameterMap();
XssSecurityManager.filtRequestParams(parameters, this.getServletPath());
}
}
XssSecurityManager.java
[java] view
plain copy
/**
* @author
* @date
* @describe 安全过滤配置管理类,统一替换可能造成XSS漏洞的字符为中文字符
*/
public class XssSecurityManager {
private static Logger log = Logger.getLogger(XssSecurityManager.class);
// 危险的javascript:关键字j av a script
private final static Pattern[] DANGEROUS_TOKENS = new Pattern[] { Pattern
.compile("^j\\s*a\\s*v\\s*a\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t\\s*:",
Pattern.CASE_INSENSITIVE) };
// javascript:替换字符串(全角中文字符)
private final static String[] DANGEROUS_TOKEN_REPLACEMENTS = new String[] { "JAVASCRIPT:" };
// 非法的字符集
private static final char[] INVALID_CHARS = new char[] { '<', '>', '\'',
'\"', '\\' };
// 统一替换可能造成XSS漏洞的字符为全角中文字符
private static final char[] VALID_CHARS = new char[] { '<', '>', '’', '“',
'\' };
// 开启xss过滤功能开关
public static boolean enable=false;
// url-patternMap(符合条件的url-param进行xss过滤)<String ArrayList>
public static Map urlPatternMap = new HashMap();
private static HashSet excludeUris=new HashSet();
private XssSecurityManager() {
// 不可被实例化
}
static {
init();
}
private static void init() {
try {
String xssConfig = "/xss_security_config.xml";
if(log.isDebugEnabled()){
log.debug("XSS config file["+xssConfig+"] init...");
}
InputStream is = XssSecurityManager.class
.getResourceAsStream(xssConfig);
if (is == null) {
log.warn("XSS config file["+xssConfig+"] not found.");
}else{
// 初始化过滤配置文件
initConfig(is);
log.info("XSS config file["+xssConfig+"] init completed.");
}
}
catch (Exception e) {
log.error("XSS config file init fail:"+e.getMessage(), e);
}
}
private static void initConfig(InputStream is) throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Element root = builder.parse(is).getDocumentElement();
//-------------------
NodeList nl=root.getElementsByTagName("enable");
Node n=null;
if(nl!=null && nl.getLength()>0){
n=((org.w3c.dom.Element)nl.item(0)).getFirstChild();
}
if(n!=null){
enable = new Boolean(n.getNodeValue().trim()).booleanValue();
}
log.info("XSS switch="+enable);
//-------------------------
nl=root.getElementsByTagName("filter-mapping");
NodeList urlPatternNodes=null;
if(nl!=null && nl.getLength()>0){
Element el=(Element)nl.item(0);
urlPatternNodes=el.getElementsByTagName("url-pattern");
//-----------------------------------------------------
NodeList nl2=el.getElementsByTagName("exclude-url");
if(nl2!=null && nl2.getLength()>0){
for(int i=0;i<nl2.getLength();i++){
Element e=(Element)urlPatternNodes.item(i);
Node paramNode=e.getFirstChild();
if(paramNode!=null){
String paramName=paramNode.getNodeValue().trim();
if(paramName.length()>0){
excludeUris.add(paramName.toLowerCase());
}
}
}
}
}
//----------------------
if(urlPatternNodes!=null && urlPatternNodes.getLength()>0){
for(int i=0;i<urlPatternNodes.getLength();i++){
Element e=(Element)urlPatternNodes.item(i);
String urlPattern=e.getAttribute("value");
if(urlPattern!=null && (urlPattern=urlPattern.trim()).length()>0){
List filtParamList = new ArrayList(2);
if(log.isDebugEnabled()){
log.debug("Xss filter mapping:"+urlPattern);
}
//-------------------------------
NodeList temp=e.getElementsByTagName("include-param");
if(temp!=null && temp.getLength()>0){
for(int m=0;m<temp.getLength();m++){
Node paramNode=(temp.item(m)).getFirstChild();
if(paramNode!=null){
String paramName=paramNode.getNodeValue().trim();
if(paramName.length()>0){
filtParamList.add(paramName);
}
}
}
}
//一定得将url转换为小写
urlPatternMap.put(urlPattern.toLowerCase(), filtParamList);
}
}
}
//----------------------
}
public static HttpServletRequest wrapRequest(HttpServletRequest httpRequest){
if(httpRequest instanceof XssHttpRequestWrapper){
// log.info("httpRequest instanceof XssHttpRequestWrapper");
//include/forword指令会重新进入此Filter
XssHttpRequestWrapper temp=(XssHttpRequestWrapper)httpRequest;
//include指令会增加参数,这里需要清理掉缓存
temp.refiltParams();
return temp;
}else{
// log.info("httpRequest is not instanceof XssHttpRequestWrapper");
return httpRequest;
}
}
public static List getFiltParamNames(String url){
//获取需要xss过滤的参数
url = url.toLowerCase();
List paramNameList = (ArrayList) urlPatternMap.get(url);
if(paramNameList==null || paramNameList.size()==0){
return null;
}
return paramNameList;
}
public static void filtRequestParams(Map params,String servletPath){
long t1=System.currentTimeMillis();
//得到需要过滤的参数名列表,如果列表是空的,则表示过滤所有参数
List filtParamNames=XssSecurityManager.getFiltParamNames(servletPath);
filtRequestParams(params, filtParamNames);
}
public static void filtRequestParams(Map params,List filtParamNames){
// 获取当前参数集
Set parameterNames = params.keySet();
Iterator it = parameterNames.iterator();
//得到需要过滤的参数名列表,如果列表是空的,则表示过滤所有参数
while (it.hasNext()) {
String paramName = (String) it.next();
if(filtParamNames==null || filtParamNames.contains(paramName) ){
String[] values = (String[])params.get(paramName);
proceedXss(values);
}
}
}
/**
* 对参数进行防止xss漏洞处理
*
* @param value
* @return
*/
private static void proceedXss(String[] values) {
for (int i = 0; i < values.length; ++i) {
String value = values[i];
if (!isNullStr(value)) {
values[i] = replaceSpecialChars(values[i]);
}
}
}
/**
* 替换非法字符以及危险关键字
*
* @param str
* @return
*/
private static String replaceSpecialChars(String str) {
for (int j = 0; j < INVALID_CHARS.length; ++j) {
if (str.indexOf(INVALID_CHARS[j]) >= 0) {
str = str.replace(INVALID_CHARS[j], VALID_CHARS[j]);
}
}
str=str.trim();
for (int i = 0; i < DANGEROUS_TOKENS.length; ++i) {
str = DANGEROUS_TOKENS[i].matcher(str).replaceAll(
DANGEROUS_TOKEN_REPLACEMENTS[i]);
}
return str;
}
/**
* 判断是否为空串,建议放到某个工具类中
*
* @param value
* @return
*/
private static boolean isNullStr(String value) {
return value == null || value.trim().length()==0;
}
public static void main(String args[]) throws Exception{
Map datas=new HashMap();
String paramName="test";
datas.put(paramName,new String[]{ "Javascript:<script>alert('yes');</script>"});
filtRequestParams(datas,"/test/sample.do");
System.out.println(((String[])datas.get(paramName))[0]);
}
}
Java Filter过滤xss注入非法参数的方法
web.xml:
[html] view
plain copy
<filter>
<filter-name>XSSFiler</filter-name>
<filter-class>
com.paic.mall.web.filter.XssSecurityFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.screen</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<url-pattern>*.shtml</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFiler</filter-name>
<servlet-name>dispatcher</servlet-name>
</filter-mapping>
XssSecurityFilter.Java
[java] view
plain copy
public class XssSecurityFilter implements Filter {
protected final Logger log = Logger.getLogger(this.getClass());
public void init(FilterConfig config) throws ServletException {
if(log.isInfoEnabled()){
log.info("XSSSecurityFilter Initializing ");
}
}
/**
* 销毁操作
*/
public void destroy() {
if(log.isInfoEnabled()){
log.info("XSSSecurityFilter destroy() end");
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest)request;
XssHttpRequestWrapper xssRequest = new XssHttpRequestWrapper(httpRequest);
httpRequest = XssSecurityManager.wrapRequest(xssRequest);
chain.doFilter(xssRequest, response);
}
}
XssHttpRequestWrapper.java
[java] view
plain copy
/**
* @author
* @date
* @describe 主要是对参数进行xss过滤,替换原始的request的getParameter相关功能
* 线程不安全
*
*/
public class XssHttpRequestWrapper extends HttpServletRequestWrapper {
protected Map parameters;
/**
* 封装http请求
*
* @param request
*/
public XssHttpRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public void setCharacterEncoding(String enc)
throws UnsupportedEncodingException {
super.setCharacterEncoding(enc);
//当编码重新设置时,重新加载重新过滤缓存。
refiltParams();
}
void refiltParams(){
parameters=null;
}
@Override
public String getParameter(String string) {
String strList[] = getParameterValues(string);
if (strList != null && strList.length > 0)
return strList[0];
else
return null;
}
@Override
public String[] getParameterValues(String string) {
if (parameters == null) {
paramXssFilter();
}
return (String[]) parameters.get(string);
}
@Override
public Map getParameterMap() {
if (parameters == null) {
paramXssFilter();
}
return parameters;
}
/**
*
* 校验参数,若含xss漏洞的字符,进行替换
*/
private void paramXssFilter() {
parameters = getRequest().getParameterMap();
XssSecurityManager.filtRequestParams(parameters, this.getServletPath());
}
}
XssSecurityManager.java
[java] view
plain copy
/**
* @author
* @date
* @describe 安全过滤配置管理类,统一替换可能造成XSS漏洞的字符为中文字符
*/
public class XssSecurityManager {
private static Logger log = Logger.getLogger(XssSecurityManager.class);
// 危险的javascript:关键字j av a script
private final static Pattern[] DANGEROUS_TOKENS = new Pattern[] { Pattern
.compile("^j\\s*a\\s*v\\s*a\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t\\s*:",
Pattern.CASE_INSENSITIVE) };
// javascript:替换字符串(全角中文字符)
private final static String[] DANGEROUS_TOKEN_REPLACEMENTS = new String[] { "JAVASCRIPT:" };
// 非法的字符集
private static final char[] INVALID_CHARS = new char[] { '<', '>', '\'',
'\"', '\\' };
// 统一替换可能造成XSS漏洞的字符为全角中文字符
private static final char[] VALID_CHARS = new char[] { '<', '>', '’', '“',
'\' };
// 开启xss过滤功能开关
public static boolean enable=false;
// url-patternMap(符合条件的url-param进行xss过滤)<String ArrayList>
public static Map urlPatternMap = new HashMap();
private static HashSet excludeUris=new HashSet();
private XssSecurityManager() {
// 不可被实例化
}
static {
init();
}
private static void init() {
try {
String xssConfig = "/xss_security_config.xml";
if(log.isDebugEnabled()){
log.debug("XSS config file["+xssConfig+"] init...");
}
InputStream is = XssSecurityManager.class
.getResourceAsStream(xssConfig);
if (is == null) {
log.warn("XSS config file["+xssConfig+"] not found.");
}else{
// 初始化过滤配置文件
initConfig(is);
log.info("XSS config file["+xssConfig+"] init completed.");
}
}
catch (Exception e) {
log.error("XSS config file init fail:"+e.getMessage(), e);
}
}
private static void initConfig(InputStream is) throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Element root = builder.parse(is).getDocumentElement();
//-------------------
NodeList nl=root.getElementsByTagName("enable");
Node n=null;
if(nl!=null && nl.getLength()>0){
n=((org.w3c.dom.Element)nl.item(0)).getFirstChild();
}
if(n!=null){
enable = new Boolean(n.getNodeValue().trim()).booleanValue();
}
log.info("XSS switch="+enable);
//-------------------------
nl=root.getElementsByTagName("filter-mapping");
NodeList urlPatternNodes=null;
if(nl!=null && nl.getLength()>0){
Element el=(Element)nl.item(0);
urlPatternNodes=el.getElementsByTagName("url-pattern");
//-----------------------------------------------------
NodeList nl2=el.getElementsByTagName("exclude-url");
if(nl2!=null && nl2.getLength()>0){
for(int i=0;i<nl2.getLength();i++){
Element e=(Element)urlPatternNodes.item(i);
Node paramNode=e.getFirstChild();
if(paramNode!=null){
String paramName=paramNode.getNodeValue().trim();
if(paramName.length()>0){
excludeUris.add(paramName.toLowerCase());
}
}
}
}
}
//----------------------
if(urlPatternNodes!=null && urlPatternNodes.getLength()>0){
for(int i=0;i<urlPatternNodes.getLength();i++){
Element e=(Element)urlPatternNodes.item(i);
String urlPattern=e.getAttribute("value");
if(urlPattern!=null && (urlPattern=urlPattern.trim()).length()>0){
List filtParamList = new ArrayList(2);
if(log.isDebugEnabled()){
log.debug("Xss filter mapping:"+urlPattern);
}
//-------------------------------
NodeList temp=e.getElementsByTagName("include-param");
if(temp!=null && temp.getLength()>0){
for(int m=0;m<temp.getLength();m++){
Node paramNode=(temp.item(m)).getFirstChild();
if(paramNode!=null){
String paramName=paramNode.getNodeValue().trim();
if(paramName.length()>0){
filtParamList.add(paramName);
}
}
}
}
//一定得将url转换为小写
urlPatternMap.put(urlPattern.toLowerCase(), filtParamList);
}
}
}
//----------------------
}
public static HttpServletRequest wrapRequest(HttpServletRequest httpRequest){
if(httpRequest instanceof XssHttpRequestWrapper){
// log.info("httpRequest instanceof XssHttpRequestWrapper");
//include/forword指令会重新进入此Filter
XssHttpRequestWrapper temp=(XssHttpRequestWrapper)httpRequest;
//include指令会增加参数,这里需要清理掉缓存
temp.refiltParams();
return temp;
}else{
// log.info("httpRequest is not instanceof XssHttpRequestWrapper");
return httpRequest;
}
}
public static List getFiltParamNames(String url){
//获取需要xss过滤的参数
url = url.toLowerCase();
List paramNameList = (ArrayList) urlPatternMap.get(url);
if(paramNameList==null || paramNameList.size()==0){
return null;
}
return paramNameList;
}
public static void filtRequestParams(Map params,String servletPath){
long t1=System.currentTimeMillis();
//得到需要过滤的参数名列表,如果列表是空的,则表示过滤所有参数
List filtParamNames=XssSecurityManager.getFiltParamNames(servletPath);
filtRequestParams(params, filtParamNames);
}
public static void filtRequestParams(Map params,List filtParamNames){
// 获取当前参数集
Set parameterNames = params.keySet();
Iterator it = parameterNames.iterator();
//得到需要过滤的参数名列表,如果列表是空的,则表示过滤所有参数
while (it.hasNext()) {
String paramName = (String) it.next();
if(filtParamNames==null || filtParamNames.contains(paramName) ){
String[] values = (String[])params.get(paramName);
proceedXss(values);
}
}
}
/**
* 对参数进行防止xss漏洞处理
*
* @param value
* @return
*/
private static void proceedXss(String[] values) {
for (int i = 0; i < values.length; ++i) {
String value = values[i];
if (!isNullStr(value)) {
values[i] = replaceSpecialChars(values[i]);
}
}
}
/**
* 替换非法字符以及危险关键字
*
* @param str
* @return
*/
private static String replaceSpecialChars(String str) {
for (int j = 0; j < INVALID_CHARS.length; ++j) {
if (str.indexOf(INVALID_CHARS[j]) >= 0) {
str = str.replace(INVALID_CHARS[j], VALID_CHARS[j]);
}
}
str=str.trim();
for (int i = 0; i < DANGEROUS_TOKENS.length; ++i) {
str = DANGEROUS_TOKENS[i].matcher(str).replaceAll(
DANGEROUS_TOKEN_REPLACEMENTS[i]);
}
return str;
}
/**
* 判断是否为空串,建议放到某个工具类中
*
* @param value
* @return
*/
private static boolean isNullStr(String value) {
return value == null || value.trim().length()==0;
}
public static void main(String args[]) throws Exception{
Map datas=new HashMap();
String paramName="test";
datas.put(paramName,new String[]{ "Javascript:<script>alert('yes');</script>"});
filtRequestParams(datas,"/test/sample.do");
System.out.println(((String[])datas.get(paramName))[0]);
}
}
相关文章推荐
- spring quartz
- java中HashSet的add的使用,以及equals和hashcode的重写
- Java正则表达式详解(Pattern类和Matcher类)
- java中trim()方法
- JAVA中的switch-each语句
- 使用intellij idea搭建MAVEN+SSM(Spring+SpringMVC+MyBatis)框架
- Selenium定位元素提示Element is not clickable at point 第一篇
- 浅谈Java中各种修饰符与访问修饰符的说明
- 解决JBoss7部署应用时Not installing optional component org.springframework.web.context.request.async.Standar
- spring boot系列 1: 第一个spring boot: Hello prj
- SpringMVC 中 jdbcTemplate.queryForList 返回结果 封装成 实体 对象
- Java中map接口 遍历map
- spring 框架jdbc连接数据库
- 谈谈对Spring IOC的理解
- Java 类和对象,如何定义Java中的类,如何使用Java中的对象,变量
- SpringBoot -- 熔断机制 Circuit Breaker
- java之yield(),sleep(),wait()区别详解
- JAVA 怎么处理高并发
- Spring MVC静态资源处理
- Java高并发编程:使用JDK5中同步技术的3个面试题