Django —— csrf 验证问题
关于 csrf 的基本了解
百度百科:CSRF(Cross-site request forgery)跨站请求伪造,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。通过伪装来自受信任用户的请求来利用受信任的网站。
简单来说就是攻击者盗用你的身份,以你的名义来发送恶意请求。比如说用户通过账号密码访问了网站A,A网站将一些cookie信息保存在浏览器中实现用户状态行为跟踪。这时用户又打开了B网站,B网站返回了一些恶意代码,并请求访问A。这样浏览器就会携带cookie以用户的权限访问A网站并执行代码。而在服务器看来,这些都是正常的用户操作。
在Django 中对csrf 的防范
Django中自带了防止csrf攻击的功能,但对于初学者来说可能不知道如何使用,并给自己带来些意外的麻烦。
例如:一个正常的表单提交操作却总是报错。
Django 中GET请求不需要csrf认证,post请求需要正确的认证才能得到正确的返回结果。
我们先处理一下对表单提交的 csrf 验证问题:一般在POST表单中加入{% csrf_token %}
<form method="POST" action="#">
{% csrf_token %}
<input name='password' value='用户密码'>
</form>
加入了这句话后,再次提交post表单就不会出现问题了。
或者是另一个思路:禁用csrf
不过这样可能带来的危害你自己要想清楚了。
全局禁用:settings文件中找到关于csrf的中间件,直接注释。对于需要保护的视图加装饰器@csrf_protect。
针对性禁用:在表单提交的对应视图函数上加上一个装饰器 @csrf_exempt
关于csrf的装饰器官方文档:https://docs.djangoproject.com/en/2.2/ref/csrf/#module-django.views.decorators.csrf
对视图类使用装饰器:https://docs.djangoproject.com/en/2.2/topics/class-based-views/intro/#decorating-the-class
-————————————————————————————————-
{% csrf_token %} 实际上是一个模板语法,将项目的token值写入到前端页面的表单中,这个值在建django项目时就已经自动生成,可以在setting中看到。
-—————————————————————————————————-
下面再看一下Ajax调用时的处理方式
使用ajax与有开启csrf验证的视图进行交互时,需要确保ajax中能够获取到csrf token值
一 从当前html页面中获取token值(cookie也同时拥有token),如果是前后端分离,是没有这个的
二 如果从session 中获取 settings设置CSRF_USE_SESSIONS=True(token存储在session而不是cookie中)
三 如果从cookie 中获取 settings设置CSRF_COOKIE_HTTPONLY=False(默认)
Django提供了一个强制设置cookie的视图装饰器: ensure_csrf_cookie。
从cookie中获取token
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
// 通过使用JavaScript Cookie库替换以上代码可以简化getCookie:
// var csrftoken = Cookies.get('csrftoken');
从html中获取
如果csrf使用了session模式或者是禁止了cookie模式,需要从html中获取csrf token
<script type="text/javascript">
// using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
// 如果是使用django模版的页面
// var csrftoken = '{% csrf_token %}'
</script>
在data中添加token发送
// 每个ajax中都需要传递csrfmiddlewaretoken
$.ajax({
url: ,url
type: "POST",
data: {
"username": username,
"password": password,
// 使用jQuery取出csrfmiddlewaretoken的值,拼接到data总
"csrfmiddlewaretoken": csrftoken
},
success: function(data){
console.log(data);
}
})
在请求头上添加token发送
这样写可以不必为每个ajax的data中添加csrf token
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
还没有评论,来说两句吧...