相关文档
- 跨站请求伪造保护 (1.8 官方文档翻译)
- Cross Site Request Forgery protection (2.2 官方文档)
- django csrf 验证问题及 csrf 原理
- django 前后端分离 csrf 验证的解决方法
- django 进阶 ( csrf、ajax )
模板获取 csrf_token
代码语言:javascript复制{{ csrf_token }} # 在html这样写,前端就会显示它
{% csrf_token %} # 在html这样写,不会显示,但是会生成一个隐藏的input框,type=hidden
django 模板里 ajax 请求携带 csrf_token 常用做法
注意:此做法 ajax 要写在 django 模板里,写在 .js 里无效。
代码语言:javascript复制<script>
// 要直接写在 HTML 文件里,才能用 {{ csrf_token }} 直接获取 csrf_token
var cur_url = window.location.href;
function visit_web() {
var url = "/index/";
$.ajax({
url: url,
data: {
cur_url: cur_url,
// 传值 csrf
csrfmiddlewaretoken: '{{ csrf_token }}'
},
type: "post",
dataType: "json",
success: function (responese) {
if (responese.status === 201) {
console.log("访问成功");
}
},
error: function (responese) {
console.log("访问失败");
}
});
}
window.onload = visit_web; // 网页加载完成后运行
</script>
ajax 请求携带 csrf_token 常用做法
1. 直接请求接口,拿到 csrf_token,设置路由为 /get_csrf_token
代码语言:javascript复制from django.middleware.csrf import get_token
def get_csrf_token(request):
return JsonResponse({'token': get_token(request)})
2. 然后既可以添加到请求头,也可以直接添加到 请求 data 的 csrfmiddlewaretoken 或 X-CSRFToken
直接给该页面所有 ajax 请求设置请求头
代码语言:javascript复制<script>
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function set_ajax_csrf_token() {
var url = "/get_csrf_token";
$.ajax({
url: url,
data: {},
type: "get",
dataType: "json",
success: function (responese) {
storage.csrf_token = responese.token;
// 给 ajax 请求设置请求头 x-csrftoken
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", responese.token);
}
}
});
},
error: function (responese) {
console.log("get csrf failed!");
}
});
}
// 运行多个函数
$(window).load(function () {
set_ajax_csrf_token();
});
</script>
拿到 csrf_token 后存起来,需要的请求添加 csrf_token(localStorage 使用总结)
代码语言:javascript复制<script>
// 定义全局变量
var storage = window.localStorage;
// 请求接口方式 获取 csrf_toke,该方法可用于 .js 文件中,可完全前后端分离
function get_token() {
var url = "/get_csrf_token";
$.ajax({
url: url,
data: {},
type: "get",
dataType: "json",
success: function (responese) {
// 保存 csrf_toke
storage.csrf_token = responese.token;
},
error: function (responese) {
console.log("get csrf failed!");
}
});
}
// 官方做法 获取 csrf_toke,该方法可用于 .js 文件中,前端必须是 django 模板渲染
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 = jQuery.trim(cookies[i]);
// 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');
// POST 请求
function post_token() {
var url = "/blog/test_csrf";
$.ajax({
url: url,
data: {
token: 1232312
},
type: "post",
dataType: "json",
// 单独给 post 请求设置 X-CSRFToken
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", storage.csrf_token);
},
success: function (responese) {
console.log("csrf test")
},
error: function (responese) {
console.log("csrf error");
}
});
}
// 运行多个函数
$(window).load(function () {
get_token();
});
// 查看 csrf_token
console.log(storage.csrf_token);
</script>
对单个视图忽略 csrf 验证
代码语言:javascript复制from django.views.decorators.csrf import csrf_exempt
# 给需要忽略的视图加 装饰器 csrf_exempt
@csrf_exempt
def test(request):
# ...
returen HttpResponse("Hello World")
注释掉 CsrfViewMiddleware 中间件 (不推荐)
注释掉 settings.py 里面的 'django.middleware.csrf.CsrfViewMiddleware' 后,所有 post请求就不会验证码 csrf_token 了,有一定安全风险。
代码语言:javascript复制MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 注释掉 csrf 验证
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]