Django REST Framework 分页链接不使用 HTTPS

2024-04-25

我正在为某个运行良好的 DRF 端点设置分页 - 但是,当部署在使用 HTTPS 的服务器上时,下一页和上一页的链接是通过http://代替https://。这会导致浏览器阻止对下一页/上一页的请求。

我已经仔细检查了初始请求是否已通过 HTTPS 发出,以及第二个答案这个问题 https://stackoverflow.com/questions/37097643/django-rest-framework-https-for-absolute-urls指出它应该在形成的 URL 中使用 HTTPS,因为请求是通过 HTTPS 发送的。

对同一问题的第一个答案也没有帮助 - 我添加了X-Forwarded-Proto行到我的 nginx 配置并重新加载,但无济于事。

DRF 文档 http://www.django-rest-framework.org/api-guide/reverse/提到reverse()应该表现得像基本的Django反向操作,但是很明显,初始请求是HTTPS,而返回的URL是HTTP。

以下是显示初始请求的几个屏幕截图(https://<domain>.com/api/leaderboard/):

响应包含next: http://<domain>.com/api/leaderboard/?page=2):

我认为这将是一个简单的设置,但在搜索此站点和 DRF 站点后未能找到任何内容。

这是我的 nginx 配置:

 location / {
    # proxy_pass http://127.0.0.1:9900;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';

    root /opt/app/client/dist;
    index index.html index.htm;

}

这个问题 https://stackoverflow.com/questions/22279893/djangorestframework-https-links-with-routers-and-viewsets包含一个非常详细的答案,但最终说 url 是使用与请求相同的协议形成的,但这里的情况似乎并非如此。我需要设置 Django SECURE_PROXY_SSL_HEADER 吗?考虑到它可能不安全的警告,我不确定。


由于这是谷歌搜索结果中出现的第一篇 SO 帖子,我认为分享我如何解决它会很有用。我的有 Kubernetes 风格,但其逻辑与其他的并没有太大不同。

我在 Django 前面使用 Kubernetes 入口控制器,所以事情可能对你来说有所不同,但我将总结我的上下文,以便你可以看看它是否对你有用:

问题

所以我遇到了与OP相同的问题,来自DRF的分页链接始终是http即使我使用 api 端点https。如果您设置了 Django REST Framework (DRF) 附带的浏览器 API,并转到 api 根页面,您可以更清楚地看到这一点。我看到 DRF 生成的所有链接都是http无论我访问该网站时使用什么协议。

我的背景

堆栈,按照从外部世界到 Django 的顺序:

  1. Kubernetes Nginx Ingress Controller(使用 LetsEncrypt 进行 SSL 设置)
  2. Ingress 规则指向 Django 服务
  3. Gunicorn 启动 Django 服务器
  4. 姜戈读到settings.py并开始处理请求

我如何调试并找出原因

  1. Dump nginx.conf入口控制器的。如果您不知道如何执行此操作:首先通过以下方式找出 pod 名称kuberctl get pods -n <namespace of your ingress controller>,写下该名称,然后转储文件kubectl exec -it -n ingress_controller_namespace ingress_controller_pod_name cat /etc/nginx/nginx.conf > nginx.conf.
  2. 看着那(这nginx.conf,检查你是否有proxy_set_header X-Forwarded-Proto $scheme; in the location您的网站域的部分,或设置代理标头的类似内容X-Forwarded-Proto适当地。默认情况下,Kubernetes nginx 入口控制器应该已经为您提供了这一行(或同等内容)。
  3. 接下来,请求被发送至 Gunicorn。一个问题是您需要添加--forwarded-allow-ips="*"到你的gunicorn命令,或者如果你知道你的nginx服务器IP,你可以限制到那个IP,这样gunicorn就会为你转发标头,否则gunicorn会去掉这些标头。所以你最终会得到像这样的命令gunicorn django_server.wsgi:application --forwarded-allow-ips="*" --workers=${PROPER_WORKER_NUM} --log-level info --bind 0.0.0.0:8001。您可以通过指定拥有 4 个工作人员workers=4,通常取决于服务器上的 CPU。这--log-level info仅用于调试目的,它是可选的。
  4. 在 Django 中,你需要有SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') in settings.py,其他答案已经提到了。您可能想知道为什么前缀HTTP_而在 nginx 中我们的标头名称是X-Forwarded-Proto。这是因为 WSGI 会将前缀添加到它识别的标头中。这行基本上是说,如果标题HTTP_X_FORWARDED_PROTO等于字符串"https",那么 Django 就会认为该请求是安全的。这将影响 Django 中的一些行为,例如你会得到request.is_secure == True, request.build_absolute_uri(None) == 'https://...',最重要的是,Django REST Framework 分页链接现在将使用https! (只要你确实通过https)

好了,现在你可以再次测试了。如果 DRF 现在为您提供 https - 恭喜。或者,如果你和我一样,经过上述尝试,仍然没有运气 - DRF 仍然产生该死的http链接。我想分享一些我在调试时的技巧:

在 Django 中打印以下值,可以通过print(), 如果你有DEBUG=True并有权访问服务器日志,或者只是将它们传递到模板上下文并在 html 页面中显示它们,如果这可以让您更轻松地在启用 SSL 的生产环境中进行测试。

  • request.is_secure():如果您无法使用 DRFhttp,你很可能会得到False.
  • request.META gives you all headers that Django received. Did the header HTTP_X_FORWARDED_PROTO show up? What value is it?
    • 我想分享的是,这对我来说是一个顿悟时刻:HTTP_X_FORWARDED_PROTO is https,https,这告诉我它以某种方式具有重复的值,并且我可能有proxy_set_header设置两次,宾果游戏!默认情况下,K8 入口控制器已经有这条线,因为我通过location-snippet,现在我有两行proxy_set_header X-Forwarded-Proto $scheme;总共。删除我的代码片段后,DRF 显示https我非常高兴能完成这件事。事情并不是那么简单,因为我想proxy_set_header将覆盖并“设置”标头值。但似乎它只是不断附加。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django REST Framework 分页链接不使用 HTTPS 的相关文章

  • 将 Django 表单中的所有 CharField 表单字段输入转换为小写

    我使用 Django 表单进行用户注册 用户可以在其中输入优惠券代码 我希望在优惠券代码字段中输入的所有字符都转换为小写 我尝试过在保存方法 自定义清理方法和自定义验证器中使用 lower 但这些方法没有运气 下面是我的代码 class S
  • Django - 缺少 1 个必需的位置参数:'request'

    我收到错误 get indiceComercioVarejista 缺少 1 个必需的位置参数 要求 当尝试访问 get indiceComercioVarejista 方法时 我不知道这是怎么回事 views from django ht
  • Django:如何判断 post_save 信号是否在新对象上触发?

    我需要对 Django 中新创建的对象进行一些后台后处理 此后处理只能在新对象上运行 而不是在刚刚更新的对象上运行 我知道在 pre save 中我可以检查该对象是否有 id 如果没有则它是一个新对象 但问题是在后处理中我需要访问id 以便
  • Http POST 删除 URL 中的端口

    我有一个用 Django 构建的网络应用程序 我目前正在家里的路由器后面的笔记本电脑上运行它 我将路由器配置为将发送到特定端口的所有流量路由到该笔记本电脑 我将 Nginx 作为 Apache 的反向代理 使用 mod wsgi 来运行 D
  • 在身份验证上运行 Django 测试时出现“重复键值”错误

    我有一个运行良好的 Django 网站 它的数据库中有少量数据 我想用它来进行测试 我已经完成了 dumpdata 来生成一些 json 固定装置 但是 当我尝试在我的应用程序 tagger 上运行测试时 我收到 Postgresql 错误
  • 如何在 Django 1.4 中自定义管理过滤器

    我是 Python 和 Django 开发的新手 我从社区提供的易于阅读的示例中学到了很多东西 但最近我想为 Django 附带的管理控制台实现一个自定义的管理过滤器 我进行了很多搜索 只发现了一些过时的方法来完成它 例如 Django 1
  • Django - 该进程无法访问该文件,因为该文件正在被另一个进程使用

    我正在尝试在 Windows 10 上运行 Django 我是 Django 的新手 我正在使用 Compressor Toolkit 我的问题是 我可以运行 manage py 但本地主机说 base html 第 9 行出错该进程无法访
  • Django 管理中的自定义验证

    我有一个非常简单的 Django 应用程序 用于记录同事的讲座 由于它非常初级 所以我使用 Django 管理本身 这是我的 models py models py from django db import models class Le
  • Django 使用用户/IP 进行日志记录

    我正在使用 logging 模块来记录大量消息 我想将 用户 request user 添加到日志中 但是 虽然它在视图函数中可用 但我不想将其传递给所有助手 有谁知道这个方法吗 我正在考虑以某种方式跟踪跟踪 直到找到参数中带有 请求 的函
  • 无法使用 django-mssql 提供程序

    有谁知道如何使用 django mssql 提供程序 我已经安装了要求 但无法让它工作 如果 settings py 中没有 sqlserver ado 它可以正常导入 testenv C Users Robin test gt pytho
  • solr + haystack + django 我在哪里放置 schema.xml?

    我刚刚安装Solr and Haystack for a Django我正在做的项目 下列的this http docs haystacksearch org dev tutorial html Haystack教程 我创建了一个 sche
  • Mac 上的 GeoDjango 和 Spatialite:C 扩展加载问题

    我正在关注GeoDjango 教程 https docs djangoproject com en dev ref contrib gis tutorial 在我的家用计算机 运行 OSX 10 8 2 的 Mac Mini 上为我的项目设
  • django-tastypie:无法访问脱水中的bundle.request(self,bundle)

    我发现有人有同样的问题 但他的安慰对我不起作用 看Django Tastypie 如何访问 Bundle 中的 Http request 对象 https stackoverflow com questions 7389632 我正在尝试应
  • django-allauth:电子邮件确认

    我已经设置了 django allauth 并在新用户注册时使用电子邮件确认 效果很好 但在确认电子邮件中 我得到 Hello from example com You re receiving this e mail because us
  • Django - 渲染到字符串无法加载 CSS

    我正在尝试使用 Django 1 8 render to string 通过管理命令将 html 转换为 pdf 而不是使用 View request 以下代码可以将模板转换为 pdf 但它无法将 CSS 加载到模板中 def html t
  • 使 Django 1.3.1 中的视图缓存过期

    我正在尝试使模型上的视图级缓存过期post save 这是通过设置的https docs djangoproject com en 1 3 topics cache from olddocs the per view cache https
  • 您将如何创建“手动”django 迁移?

    我发现我可以使用 django 项目中的 postgres 数据库设置列的默认值migrations RunSQL some sql 我目前正在通过添加列 makemigrations 然后删除列 makemigrations 然后手动修改
  • Django:出于测试目的阻止互联网连接

    我想确保我的单元测试不会尝试连接到互联网 有没有办法在连接时引发异常 有一个类似的问题Python 出于测试目的阻止网络连接 https stackoverflow com questions 18601828 python block n
  • 如何修改查询集并将其另存为新对象?

    我需要查询特定模型的一组对象 更改单个属性 列 帐户 然后将整个查询集的对象保存为新对象 行 换句话说 我想复制对象 并在重复项上更改单个属性 帐户 我基本上是创建一个新帐户 然后检查每个模型并将以前帐户的对象复制到新帐户 因此我将使用不同
  • Django:单击按钮加载另一个模板

    我已经在 django 项目上工作了几个星期 只是玩玩以便掌握它的窍门 我有点困惑 我现在有一个名为 home html 的模板 我想知道是否可以将另一个名为 profile html 的模板设置为 home html 模板上的链接 我有一

随机推荐