暑假电商项目一直有一个问题没有处理,用Nginx反代后端后,前端发送POST请求,有一个CSRF token missing or incorrect.
错误,注销掉中间件CsrfViewMiddleware
也没有用,最后发现是DRF
的SessionAuthentication
认证模块的问题,当时选择了关掉这个认证模块,然后自己给后台写的视图认证就带来了问题,所以还是选择修复一下。
问题复现#
当时的Nignx配置大概是这样的
1
2
3
4
5
6
|
location ~* /.*$ {
expires -1;
proxy_pass http://127.0.0.1:8000;
.....
add_header X-Cache $upstream_cache_status;
}
|
只把Cookie转发过去了,于是出现了问题。
解决思路#
后面看到了CSRF Failed: CSRF token missing or incorrect_爱吃鱼虾的博客-CSDN博客
文章里提到:
django,会对合法的跨域访问做这样的检验,cookies里面存储的’csrftoken’,和post的header里面的字段”X-CSRFToken’作比较,只有两者匹配,才能通过跨域检验。
于是我去看源代码验证了一下
1
2
3
4
5
6
|
# request_csrf_token是从Headers中获取的
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
# csrf_token是从Cookies里面获取的
# 获取这个时调用了_get_token,还有一些其他操作,这里简化一下
csrf_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
|
CSRF_HEADER_NAME
和CSRF_COOKIE_NAME
的默认值可在Django
包目录下/conf/global_settings.py
中查看
1
2
3
|
CSRF_COOKIE_NAME = 'csrftoken'
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
|
解决办法#
选择了和上面博客一样的解决方案,转发一下HTTP_X_CSRFTOKEN
1
2
3
4
5
6
7
8
9
10
11
12
|
location ~* /.*$ {
expires -1;
proxy_pass http://127.0.0.1:8000;
# 获取请求头中的cookie中csrftoken的值,赋值给X-CSRFToken;
set $CSRFTOKEN "";
if ($http_cookie ~* "csrftoken=(.+?)(?=;|$)") {
set $CSRFTOKEN "$1";
}
proxy_set_header HTTP_X_CSRFTOKEN $CSRFTOKEN; # 设置X-CSRFToken
.....
add_header X-Cache $upstream_cache_status;
}
|