暑假电商项目一直有一个问题没有处理,用Nginx反代后端后,前端发送POST请求,有一个CSRF token missing or incorrect.错误,注销掉中间件CsrfViewMiddleware也没有用,最后发现是DRFSessionAuthentication认证模块会校验CSRF。

问题复现

当时的Nignx配置大概是这样的

1
2
3
4
location ^~ / {
    proxy_pass http://127.0.0.1:8000;
    # .....
}

解决思路

后面看到了CSRF Failed: CSRF token missing or incorrect_爱吃鱼虾的博客-CSDN博客

文章里提到:

django,会对合法的跨域访问做这样的检验,cookies里面存储的’csrftoken’,和post的header里面的字段’X-CSRFToken’作比较,只有两者匹配,才能通过跨域检验。

于是我去看源代码验证了一下

5f92a0da8422d39024bd17f275563759.png

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_NAMECSRF_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
location ^~ / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header X-CSRFToken $cookie_csrftoken;
    # .....
}