csrf_ajax提交
csrf攻击
网站是通过cookie
来实现登录功能的。而cookie
只要存在浏览器中,那么浏览器在访问这个cookie
的服务器的时候,就会自动的携带cookie
信息到服务器上去。
那么这时候就存在一个漏洞了,如果你访问了一个别有用心或病毒网站,这个网站可以在网页源代码中插入js代码,使用js代码给其他服务器发送请求(比如ICBC的转账请求)。
那么因为在发送请求的时候,浏览器会自动的把cookie
发送给对应的服务器,这时候相应的服务器(比如ICBC网站),就不知道这个请求是伪造的,就被欺骗过去了。
从而达到在用户不知情的情况下,给某个服务器发送了一个请求(比如转账)。
预防csrf攻击
CSRF攻击的要点就是在向服务器发送请求的时候,相应的cookie
会自动的发送给对应的服务器。
造成服务器不知道这个请求是用户发起的还是伪造的。这时候,我们可以在用户每次访问有表单的页面的时候,在网页源代码中加一个随机的字符串叫做csrf_token
,
在cookie
中也加入一个相同值的csrf_token
字符串。
以后给服务器发送请求的时候,必须在body
中以及cookie
中都携带csrf_token
,
服务器只有检测到cookie
中的csrf_token
和body
中的csrf_token
都相同,才认为这个请求是正常的,否则就是伪造的。
django
在settings.MIDDLEWARE
中添加CsrfMiddleware
中间件。
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.middleware.gzip.GZipMiddleware', 4 'django.contrib.sessions.middleware.SessionMiddleware', 5 'django.middleware.common.CommonMiddleware', 6 'django.middleware.csrf.CsrfViewMiddleware', 7 'django.contrib.auth.middleware.AuthenticationMiddleware', 8 'django.contrib.messages.middleware.MessageMiddleware', 9 'django.middleware.clickjacking.XFrameOptionsMiddleware' 10 ]
在模板中添加一个隐藏域input
1 <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
flask
使用flask_wtf.CSRFProtect
来包裹app
。
1 from flask_wtf import CSRFProtect 2 3 app = Flask(__name__) 4 CSRFProtect(app) 5 6 7 if __name__ == '__main__': 8 app.run()
模板中
添加一个input隐藏域
1 <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
ajax提交csrf
封装一个myajax.js包来使用
1 var myajax = { 2 'get':function(args) { 3 args['method'] = 'get'; 4 this.ajax(args); 5 }, 6 'post':function(args) { 7 args['method'] = 'post'; 8 this.ajax(args); 9 }, 10 'ajax':function(args) { 11 // 设置csrftoken 12 this._ajaxSetup(); 13 $.ajax(args); 14 }, 15 '_ajaxSetup': function() { 16 $.ajaxSetup({ 17 'beforeSend':function(xhr,settings) { 18 if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) { 19 var csrftoken = $('meta[name=csrf-token]').attr('content'); 20 xhr.setRequestHeader("X-CSRFToken", csrftoken) 21 } 22 } 23 }); 24 } 25 };
使用时调用myajax.post()
1 myajax.post({ 2 'url': '/login/', 3 4 'data': { 5 6 username:username, 7 password:password 8 }
注意需在meta标签中加上name='csrf-token', content='{{csrf_token()}}'