java网页程序采用 spring 防止 csrf 攻击.

摘要: 经常开发银行的应用,在安全性方面要求比较高,在安全性保护方面,csrf 攻击是必须测试的项目之一,关于什么是 csrf 攻击,我不想多做解释,网上已经介绍够多了,可以参看 IBM Developer works 的文章 http://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/ 这篇文章介绍了 csrf  的危害和一般解决办法,在实际开发过程中,有一些参考价值。但事实上在我经历过的银行项目开发过程中,基本都会采用 spring 框架,所以完全可以不用自己开发 filter 去拦截 csrf 攻击的请求,而直接采用实现 spring 提供的 HandlerInterceptor 来实现。 从本质上来说,这也是一个 filter.  我这里就直接实现它来 防止 csrf 攻击.

经常开发银行的应用,在安全性方面要求比较高,在安全性保护方面,csrf 攻击是必须测试的项目之一,关于什么是 csrf 攻击,我不想多做解释,网上已经介绍够多了,可以参看 IBM Developer works 的文章 http://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/ 这篇文章介绍了 csrf 的危害和一般解决办法,在实际开发过程中,有一些参考价值。

但事实上在我经历过的银行项目开发过程中,基本都会采用 spring 框架,所以完全可以不用自己开发 filter 去拦截 csrf 攻击的请求,而直接采用实现 spring 提供的 HandlerInterceptor 来实现。 从本质上来说,这也是一个 filter. 我这里就直接实现它来 防止 csrf 攻击.

基本思路:
1. 用户登录之后,后台程序生产一个 csrftoken 的 token ,放在 cookies 中,并且记录在 session 中。
2. 当客户端发出请求的访问后台程序的时候,经过自己实现的HandlerInterceptor 来拦截.
3. 拦截的基本方法是检查请求的参数中是否有csrftoken ,并检查这个值,是否合法有效(不为空,并且得到的参数等于cookies 中保存的值,而且还要等于session 中的值,那么就是合法的)

直接上代码,需要相关 spring 的jar 包,自己可以准备好,代码如下:

package com.yihaomen.intercepter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class CsrfIntercepter implements HandlerInterceptor { 	

public  static final String CSRFNUMBER = "csrftoken";
	public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
	
		String keyFromRequestParam = (String) request.getParameter(CSRFNUMBER);
		String keyFromCookies=""; 
		boolean result=false;
		Cookie[] cookies = request.getCookies(); 
		if(cookies!=null){
			for (int i = 0; i < cookies.length; i++) {	
			    String name = cookies[i].getName(); 
			    if(CSRFNUMBER.equals(name) ) {	
			        keyFromCookies= cookies[i].getValue();	
			    }	
			}
		}
	
		if((keyFromRequestParam!=null && keyFromRequestParam.length()>0 && 
				keyFromRequestParam.equals(keyFromCookies) &&
		        keyFromRequestParam.equals((String)request.getSession().getAttribute(CSRFNUMBER)))) { 
			result=true;
		}else{
		    request.getRequestDispatcher("/error/400").forward(request, response);
		}
		
		return result;
	}
	
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, Exception arg3) throws Exception {
		
	}
	
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {
		
	}
}



这样就可以实现在 j2ee 应用中拦截 csrf 攻击了。

上一篇: Django 中 如何使用 settings.py 中的常量
下一篇: java 防止 XSS 攻击的常用方法总结.

Avatar

fllf 评论于: 2018-01-04

@cocal

说的很对。

Avatar

hellocpu 评论于: 2017-02-17

楼上说的是的,如果还把信息放在COOKIE中,那么等于白做了这个防御。

Avatar

coolbaby 评论于: 2015-02-25

这样做是可以的,攻击者永远无法同时知道cookies 中的参数与request 中传递的参数,而服务端比较是 三者都要比较的,所以是可以防止csrf 攻击的。

Avatar

cocal 评论于: 2015-02-10

你好 感谢的文章。 
但是你这种方法仍然是将token放在cookies中。 仍然是没法防止csrf攻击的。
因为csrf攻击实在用户登录Session没有完全失效的情况下,用 用户的cookies去发送请求的。 服务器仍然能获取到cookies中的验证参数。
所以这种情况任然不能避免,看了IBM那篇文章比较推荐的方法,是在页面加请求参数来验证。
欢迎讨论 感谢~
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号