java web应用程序防止 csrf 攻击的方法,参考这里 java网页程序采用 spring 防止 csrf 攻击.,但这只是攻击的一种方式,还有其他方式,比如今天要记录的 XSS 攻击, XSS 攻击的专业解释,可以在网上搜索一下,参考百度百科的解释 http://baike.baidu.com/view/2161269.htm, 但在实际的应用中如何去防止这种攻击呢,下面给出几种办法.
1. 自己写 filter 拦截来实现,但要注意的时,在WEB.XML 中配置 filter 的时候,请将这个 filter 放在第一位.
2. 采用开源的实现 ESAPI library ,参考网址: https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API
3. 可以采用spring 里面提供的工具类来实现.
一, 第一种方法。
配置过滤器
publicclassXSSFilterimplementsFilter{
@Override
publicvoid init(FilterConfig filterConfig)throwsServletException{
}
@Override
publicvoid destroy(){
}
@Override
publicvoid doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
throwsIOException,ServletException{
chain.doFilter(newXSSRequestWrapper((HttpServletRequest) request), response);
}}
再实现 ServletRequest 的包装类
import java.util.regex.Pattern;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;publicclassXSSRequestWrapperextendsHttpServletRequestWrapper{
publicXSSRequestWrapper(HttpServletRequest servletRequest){
super(servletRequest);
}
@Override
publicString[] getParameterValues(String parameter){
String[] values =super.getParameterValues(parameter);
if(values ==null){
returnnull;
}
int count = values.length;
String[] encodedValues =newString[count];
for(int i =0; i < count; i++){
encodedValues[i]= stripXSS(values[i]);
}
return encodedValues;
}
@Override
publicString getParameter(String parameter){
String value =super.getParameter(parameter);
return stripXSS(value);
}
@Override
publicString getHeader(String name){
String value =super.getHeader(name);
return stripXSS(value);
}
privateString stripXSS(String value){
if(value !=null){
// NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
// avoid encoded attacks.
// value = ESAPI.encoder().canonicalize(value);
// Avoid null characters
value = value.replaceAll("","");
// Avoid anything between script tags
Pattern scriptPattern =Pattern.compile("(.*?)",Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of expression
scriptPattern =Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern =Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Remove any lonesome tag
scriptPattern =Pattern.compile("",Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Remove any lonesome tag
scriptPattern =Pattern.compile("",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid eval(...) expressions
scriptPattern =Pattern.compile("eval\\((.*?)\\)",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid expression(...) expressions
scriptPattern =Pattern.compile("expression\\((.*?)\\)",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid javascript:... expressions
scriptPattern =Pattern.compile("javascript:",Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid vbscript:... expressions
scriptPattern =Pattern.compile("vbscript:",Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid οnlοad= expressions
scriptPattern =Pattern.compile("onload(.*?)=",Pattern.CASE_INSENSITIVE |Pattern.MULTILINE |Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
}
return value;
}}
例子中注释的部分,就是采用 ESAPI library 来防止XSS攻击的,推荐使用.
当然,我还看到这样一种办法,将所有的编程全角字符的解决方式,但个人觉得并没有上面这种用正则表达式替换的好
privatestaticString xssEncode(String s){
if(s ==null|| s.equals("")){
return s;
}
StringBuilder sb =newStringBuilder(s.length()+16);
for(int i =0; i < s.length(); i++){
char c = s.charAt(i);
switch(c){
case'>':
sb.append('>');// 全角大于号
break;
case'
sb.append('<');// 全角小于号
break;
case'\'':
sb.append('\\');
sb.append('\'');
sb.append('\\');
sb.append('\'');
break;
case'\"':
sb.append('\\');
sb.append('\"');// 全角双引号
break;
case'&':
sb.append('&');// 全角
break;
case'\\':
sb.append('\');// 全角斜线
break;
case'#':
sb.append('#');// 全角井号
break;
case':':
sb.append(':');// 全角冒号
break;
case'%':
sb.append("\\\\%");
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}
当然,还有如下更简单的方式:
privateString cleanXSS(String value){
//You'll need to remove the spaces from the html entities below
value = value.replaceAll("","& gt;");
value = value.replaceAll("\\(","& #40;").replaceAll("\\)","& #41;");
value = value.replaceAll("'","& #39;");
value = value.replaceAll("eval\\((.*)\\)","");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']","\"\"");
value = value.replaceAll("script","");
return value;
}
在后台或者用spring 如何实现呢:
首先添加一个jar包:commons-lang-2.5.jar ,然后在后台调用这些函数:
StringEscapeUtils.escapeHtml(string);StringEscapeUtils.escapeJavaScript(string);StringEscapeUtils.escapeSql(string);
当然,我记得在spring 里面好像有一个 HtmlUtils.htmlEscape , 同样可以做到 过滤 XSS 攻击。从上面的介绍可以看出,防止 XSS 攻击并不难,就是要小心。
===============================================================
在apache commons-lang(2.3以上版本)中为我们提供了一个方便做转义的 工具类,主要是为了防止sql注入,xss注入攻击的功能。总共提供了以下几个方法:
1.escapeSql 提供sql转移功能,防止sql注入攻击,例如典型的万能密码攻击' ' or 1=1 ' '
StringBuffer sql = new StringBuffer("select key_sn,remark,create_date from tb_selogon_key where 1=1 ");
if(!CommUtil.isEmpty(keyWord)){
sql.append(" and like '%" + StringEscapeUtils.escapeSql(keyWord) + "%'");
}
StringBuffer sql = new StringBuffer("select key_sn,remark,create_date from tb_selogon_key where 1=1 ");
if(!CommUtil.isEmpty(keyWord)){
sql.append(" and like '%" + StringEscapeUtils.escapeSql(keyWord) + "%'");
}
2.escapeHtml /unescapeHtml 转义/反转义html脚本
System.out.println(StringEscapeUtils.escapeHtml("dddd"));
输出结果为:<a>dddd</a>
System.out.println(StringEscapeUtils.escapeHtml("dddd"));
输出结果为:<a>dddd</a>
System.out.println(StringEscapeUtils.unescapeHtml("<a>dddd</a>"));
输出为:ddd
System.out.println(StringEscapeUtils.unescapeHtml("<a>dddd</a>"));
输出为:ddd
3.escapeJavascript/unescapeJavascript 转义/反转义js脚本
System.out.println(StringEscapeUtils.escapeJavaScript(""));
输出为:<script>alert('111')</script>
System.out.println(StringEscapeUtils.escapeJavaScript(""));
输出为:<script>alert('111')</script>
4.escapeJava/unescapeJava 把字符串转为unicode编码
System.out.println(StringEscapeUtils.escapeJava("中国"));
输出为:用escapeJava方法转义之后的字符串为:/u4E2D/u56FD/u5171/u4EA7/u515A
==============================================
apache工具包common-lang中有一个很有用的处理字符串的工具类,其中之一就是StringEscapeUtils,这个工具类是在2.3版本以上加上的去的,利用它能很方便的进行html,xml,java等的转义与反转义,而且还能对关键字符串进行处理预防SQL注入,不过好像common-lang3.0以后我看着好像没这个处理SQL语句的方法了,想用的话前提时引入对应的jar包,以下为它的部分方法:
它的方法,全是静态,直接用类调用即可,下边来根据代码看看它们几个的用法和效果,一看一目了然:
package stringescapeutils;
import org.apache.commons.lang.StringEscapeUtils;
public class StringEscapeUtilsTest {
public static void main(String args[]){
String sql="1' or '1'='1";
System.out.println("防SQL注入:"+StringEscapeUtils.escapeSql(sql)); //防SQL注入
System.out.println("转义HTML,注意汉字:"+StringEscapeUtils.escapeHtml("chen磊 xing")); //转义HTML,注意汉字
System.out.println("反转义HTML:"+StringEscapeUtils.unescapeHtml("chen磊 xing")); //反转义HTML
System.out.println("转成Unicode编码:"+StringEscapeUtils.escapeJava("陈磊兴")); //转义成Unicode编码
System.out.println("转义XML:"+StringEscapeUtils.escapeXml("陈磊兴")); //转义xml
System.out.println("反转义XML:"+StringEscapeUtils.unescapeXml("陈磊兴")); //转义xml
}
}
输入结果:
防SQL注入:1'' or ''1''=''1
转义HTML,注意汉字:chen磊 xing
反转义HTML:chen磊 xing
转成Unicode编码:\u9648\u78CA\u5174
转义XML:陈磊兴
反转义XML:陈磊兴
http://blog.csdn.net/chenleixing/article/details/43456987
http://www.cnblogs.com/thinkpad/p/4837841.html
http://blog.csdn.net/joeyon1985/article/details/43527987