因浏览器未发送Referer HTTP头导致Django项目CSRF验证失败的原因

问题

前段时间,做了一次服务器减负的同时,也把所有的遗留网站都加上了 HTTPS 支持,让客户免受推荐 HTTPS 证书销售公司的电话骚扰(他们的话术很吓人,客户听了以后会害怕地找我,这就很让我烦心了)。

因为遗留的都是企业官网,很少人会登陆更新内容,所以很久以后,客户才来联系我说后台登陆不上了。我一试,发现出现了 403 错误:

复制代码
禁止访问 (403)

CSRF验证失败. 请求被中断.

您看到此消息是由于HTTPS站点需要浏览器发送 'Referer HTTP头',但是目前没有被发送。出于安全考虑,浏览器必须发送该HTTP头,以确保您的浏览器没有被第三方劫持。

如果您已经设置浏览器禁用 'Referer' 头,请重新启用,至少针对这个站点,全部HTTPS请求,或者同源请求(same-origin)启用发送该HTTP头。

更多信息请设置选项DEBUG=True。

探索

奇哉!我记得我们的Django项目一直是有做 CSRF 验证的。但不管三七二十一,先爬上服务器看看。配置文件里的corsheaders.middleware.CorsMiddlewarecorsheaders都好好地躺在MIDDLEWAREINSTALLED_APPS配置项里。

重新看出错信息,有一段如果您已经设置浏览器禁用 'Referer' 头,请重新启用,这很是奇怪。都不知道浏览器还能禁用 Referer 头,搜索也找不到相关配置。搞得一头雾水,好不头大!

复制CSRF验证失败. 请求被中断.去搜索,也是一些关于开启Cookies和需要在form表单中增加{% csrf_token %}字段之类的常规方法,根据没有和Referer HTTP头 相关的片段,而这些提及的方向我们都已经做好了。

端倪

看来只能使用找Bug的根本大法:看源代码了。打开目录发现重载了页码模板,打开页面模板搜索referer关键字,并无收获。再仔细看,发现还重载了base.html这个基础页面,再找开就发现里面有一行:

html 复制代码
<meta name="referrer" content="never">

一看这行,就知道是控制了当发送 HTTP 请求的时候,不要发送Referer头了!

把这一行去掉,再测试,果然解决问题。然后查阅参考文档,发现这个 meta 项的默认值是:strict-origin-when-cross-origin,于是重新改回:

html 复制代码
<meta name="referrer" content="strict-origin-when-cross-origin">

测试可用,提交代码。收工。

小结

不知道为什么会出现这样的错误,想来可能是之前的同事从别处直接复制了一个文件,遗留了快十年吧。估计也不会有其他人遇到同样的情况,在此记之以自娱矣。

相关推荐
码界筑梦坊1 小时前
353-基于Python的大湾区气候数据可视化分析系统
开发语言·python·信息可视化·数据分析·django·vue·毕业设计
LlNingyu1 小时前
文艺复兴,什么是CSRF,常见形式(一)
前端·安全·web安全·csrf
未来转换2 小时前
计算机网络之HTTP协议详解
网络协议·计算机网络·http
badhope5 小时前
前端已死?前端角色演进的四维技术证据链(2026年实证)
react.js·django·node.js
亿牛云爬虫专家7 小时前
爬虫踩坑实录:OkHttp 接入爬虫代理报 Too many tunnel connections attempted 深度解析
爬虫·okhttp·https·爬虫代理·connect·隧道代理·ip 切换
源码之家8 小时前
计算机毕业设计:Python汽车销量数据采集分析可视化系统 Flask框架 requests爬虫 可视化 车辆 大数据 机器学习 hadoop(建议收藏)✅
大数据·爬虫·python·django·flask·课程设计·美食
m0_651593918 小时前
从羊肠小道到智能高速:HTTP1到HTTP3的演进之路
http
zl_dfq9 小时前
计算机网络 之 【https协议】(数字摘要、密钥、数字证书)
网络协议·计算机网络·https
coderlin_10 小时前
Django DRF开发
python·django·sqlite
sxhcwgcy10 小时前
Elasticsearch(ES)基础查询语法的使用
python·elasticsearch·django