Cross-site request forgery
CSRF的全称是`Cross-site request forgery`,简单的意思就是用户在可信网站登录后获得可信cookie,未退出之前,访问了一个恶意网站,恶意网站夹带攻击性代码要求访问一个第三方网站,浏览器在接收到恶意网站的请求后,在用户不知情的情况下携带安全网站给的Cookie信息,向其发出请求。可信网站并不知道该请求其实是由恶意网站发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自恶意网站的恶意代码被执行
How to guard against CSRF of Django
Let's look at CsrfViewMiddleware
some of this content source middleware
...
request_csrf_token = ""
if request.method == "POST":
try:
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '') # POST请求是在这里获取到的
except IOError:
# Handle a broken connection before we've completed reading
# the POST data. process_view shouldn't raise any
# exceptions, so we'll ignore and serve the user a 403
# (assuming they're still listening, which they probably
# aren't because of the error).
pass
if request_csrf_token == "":
# Fall back to X-CSRFToken, to make things easier for AJAX,
# and possible for PUT/DELETE.
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '') # ajax请求是在获取的
request_csrf_token = _sanitize_token(request_csrf_token)
if not _compare_salted_tokens(request_csrf_token, csrf_token):
return self._reject(request, REASON_BAD_TOKEN)
...
When we manually output settings.CSRF_HEADER_NAME
the result is this:
from django.conf import settings
print(settings.CSRF_HEADER_NAME)
>>> HTTP_X_CSRFTOKEN
Django uses django.middleware.csrf.CsrfViewMiddleware
this middleware to complete the verification. There are two ways in django in defense csrf attacks:
1. Add in the form formcsrf_token
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div>
<form action="/login/" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="提交">
</form>
</div>
<script>
</script>
</body>
</html>
In the form of this plus {% csrf_token %}
the fact he essentially creates a hidden input tag value and the input value is a random string generated web page to the server when the get, as follows:
When the form submitted by passing this value is sent to the server do the verification
2. Add in the headerX-CSRFToken
- When we use the general ajax submitted
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function () {
$('#btn').click(function () {
$.ajax({
url:'/login/',
type:'POST',
data:$('#f1').serialize(),
success:function () {
}
})
})
})
</script>
Ajax write will appear403CSRF verification failed. Request aborted.
Ajax then we should add in header in CSRF_HEADER_NAME
the corresponding value HTTP_X_CSRFTOKEN
, but because of django will automatically add the header fields of the header HTTP_
as a distinguished, so the real value we should add that X_CSRFTOKEN
, but they can not because the request header underlined , it can only be written as the X-CSRFTOKEN
official way of writing X-CSRFtoken
, but both are possible.
Js to get through csrftoken
this cookie and added to the header
Correct ajax request should be like this
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function () {
$('#btn').click(function () {
$.ajax({
url:'/login/',
type:'POST',
headers:{"X-CSRFtoken": $.cookie('csrftoken'),}
data:$('#f1').serialize(),
success:function (arg) {
location.href="/index/"
}
})
})
})
</script>
3. All ajax requests are added to this page headers
$.ajaxSetup({
beforeSend: function(xhr,settings){
xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
}
});
django selected using CSRF
Part of the set:from django.views.decorators.csrf import csrf_exempt,csrf_protect
- @csrf_protect, forcibly set preventing cross-site request forgery function to a function of the current, even if the settings are not set the overall middleware
- @csrf_exempt, cancels the current function CSRF prevention function, even if the global settings set in the middleware.
Global Settings:
middlewaredjango.middleware.csrf.CsrfViewMiddleware