问题解析
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。
场景:1论坛提交的链接2钓鱼网站
例子:假如一家银行用以运行转账操作的URL地址如下:http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName那么,一个恶意攻击者可以在另一个网站上放置如下代码: <imgsrc="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">如果有账户名为Alice的用户访问了恶意站点,而她之前刚访问过银行不久,登录信息尚未过期,那么她就会损失1000资金
通常情况下,有三种方法被广泛用来防御CSRF攻击:验证token,验证HTTP请求的Referer,还有验证XMLHttpRequests里的自定义header。
解决方案
配置过滤器拦截refer非本网站的请求
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CSRFilter implements Filter {
private String[] verifyReferer = null;
private static Log log = LogFactory.getLog(CSRFilter.class);
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String referer = ((HttpServletRequest)request).getHeader("Referer");
boolean b = false;
for(String vReferer : verifyReferer){
if(referer==null || referer.trim().startsWith(vReferer)){
b = true;
chain.doFilter(request, response);
break;
}
}
if(!b){
log.error("疑似CSRF攻击,referer:"+referer);
}
}
public void init(FilterConfig filterConfig) throws ServletException {
String referer = filterConfig.getInitParameter("referer");
this.verifyReferer = referer.split(",");
}
}
web.xml配置过滤器
<filter>
<filter-name>csrfFilter</filter-name>
<filter-class>com.filter.CSRFilter</filter-class>
<init-param>
<param-name>referer</param-name>
<param-value>localhost</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>csrfFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>