环境:
Seafile v12.0.11 Pro 非 Docker 部署
Ubuntu 22.04.5 LTS、Python 3.10.12
登录用户时,报错
Forbidden (403)
CSRF verification failed. Request aborted.
看了 logs 目录下的 seahub.log 日志,有个 warning 级别信息
[2025-04-15 21:19:12] [WARNING] django.security.csrf:241 log_response Forbidden (Origin checking failed - https://example.0z.gs does not match any trusted origins.): /accounts/login/
我是根据官方文档操作的:https://docs.djangoproject.com/en/3.2/ref/settings/#csrf-trusted-origins
已经加了相关域名,还是这样,但是发现如果写成 https://test.example.com
形式是可以的,可是文档说了可以使用通配符的
绕了下圈子,最后发现是文档应该漏写了 *
?
实测发现接受值的格式跟文档里面的 ALLOWED_HOSTS
字段的格式不一样,Django 文档没有在 CSRF_TRUSTED_ORIGINS
说明中使用 *
,我以为还是使用 .example.com
形式,但是是不支持的,需要改为 *.example.com
格式
ALLOWED_HOSTS
字段相反,需要通配符匹配子域名时,必须省略 *
,格式为 .example.com
,加 *
反而会报错,并且需要指定协议 http/https,非标准端口情况下得附加端口
[ERROR] django.security.DisallowedHost:124 response_for_exception Invalid HTTP_HOST header: 'test.example.com'. You may need to add 'test.example.com' to ALLOWED_HOSTS.
迷之操作
如果不需要通配符,可以在 CSRF_TRUSTED_ORIGINS
写明具体协议和端口,如 http://api.example.com:8011
、https://api.test.com:11451
最后改为类似这样就行了,重启 seafile 相关服务,删除 conf 目录下的 pycache 缓存后生效
ALLOWED_HOSTS = ['.example.com', '.localhost', '127.0.0.1','.example.org', '.example.net', 'test.org']
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Strict'
CSRF_TRUSTED_ORIGINS = ['http://*.example.com', 'http://*.example.org', 'http://*.example.net', 'http://*.test.org', 'https://*.example.com', 'https://*.example.org', 'https://*.example.net', 'https://*.test.org', 'http://test.net:8123', 'https://114514.test.net:2443']
踩坑的文档原话
CSRF_TRUSTED_ORIGINS
Default: [] (Empty list)A list of hosts which are trusted origins for unsafe requests (e.g. POST). For a secure unsafe request, Django’s CSRF protection requires that the request have a Referer header that matches the origin present in the Host header. This prevents, for example, a POST request from subdomain.example.com from succeeding against api.example.com. If you need cross-origin unsafe requests over HTTPS, continuing the example, add "subdomain.example.com" to this list. The setting also supports subdomains, so you could add ".example.com", for example, to allow access from all subdomains of example.com.
通配符示例的确是没加 *
另外如果视频无法在线播放,也是 CSRF 的问题,虽然也是监听的本地端口,然后 Nginx 反代对外提供服务,但是ALLOWED_HOSTS
依然需要加白 127.0.0.1
,不然日志会有相关 CSRF 报错
[ERROR] django.security.DisallowedHost:124 response_for_exception Invalid HTTP_HOST header: '127.0.0.1:8000'. You may need to add '127.0.0.1' to ALLOWED_HOSTS.