如何只在Heroku https上制作python?

时间:2011-12-08 19:41:42

标签: python django ssl https heroku

我在Heroku(Cedar堆栈)上有python / django应用程序,并希望只通过https访问它。我启用了“ssl piggyback”-option,并可以通过https连接到它。

但是,禁用http访问或重定向到https的最佳方法是什么?

6 个答案:

答案 0 :(得分:64)

将@CraigKerstiens和@allanlei的答案结合到我测试过的内容中,并验证可行。当请求是ssl时,Heroku将HTTP_X_FORWARDED_PROTO设置为https,我们可以使用它来检查:

from django.conf import settings
from django.http import HttpResponseRedirect


class SSLMiddleware(object):

    def process_request(self, request):
        if not any([settings.DEBUG, request.is_secure(), request.META.get("HTTP_X_FORWARDED_PROTO", "") == 'https']):
            url = request.build_absolute_uri(request.get_full_path())
            secure_url = url.replace("http://", "https://")
            return HttpResponseRedirect(secure_url)

答案 1 :(得分:47)

Django 1.8将支持非HTTPS重定向(从django-secure集成):

SECURE_SSL_REDIRECT = True # [1]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

为了处理SECURE_SSL_REDIRECT,您必须使用SecurityMiddleware

MIDDLEWARE = [
    ...
    'django.middleware.security.SecurityMiddleware',
]

[1] https://docs.djangoproject.com/en/1.8/ref/settings/#secure-ssl-redirect

答案 2 :(得分:13)

不确定@ CraigKerstiens的答案是否考虑到request.is_secure()总是返回False,如果在Heroku的反向代理后面而不是“修复”。如果我没记错的话,这将导致HTTP重定向循环。

如果您使用gunicorn运行Django,另一种方法是将以下内容添加到gunicorn的配置

secure_scheme_headers = {
    'X-FORWARDED-PROTO': 'https'
}

在Procfile中运行类似的东西

web: python manage.py run_gunicorn -b 0.0.0.0:$PORT -c config/gunicorn.conf

通过设置gunicorn的secure-scheme-headerrequest.is_secure()将在https请求中正确返回True。请参阅Gunicorn Config

现在,@ CraigKerstiens的中间件可以正常运行,包括在您的应用中对request.is_secure()的任何来电。

注意:Django也有相同的配置设置调用SECURE_PROXY_SSL_HEADER,但是在开发版本中。

答案 3 :(得分:6)

您使用的是什么框架?如果你正在使用Django,你可以简单地使用一些类似于:

的中间件
import re

from django.conf import settings
from django.core import urlresolvers
from django.http import HttpResponse, HttpResponseRedirect


class SSLMiddleware(object):

    def process_request(self, request):
        if not any([settings.DEBUG, request.is_secure()]):
            url = request.build_absolute_uri(request.get_full_path())
            secure_url = url.replace("http://", "https://")
            return HttpResponseRedirect(secure_url)

答案 4 :(得分:4)

如果你正在使用Flask,这很有效:

1)“pip install flask-sslify”

(github在这里:https://github.com/kennethreitz/flask-sslify

2)包括以下几行:

from flask_sslify import SSLify
if 'DYNO' in os.environ: # only trigger SSLify if the app is running on Heroku
    sslify = SSLify(app)

答案 5 :(得分:0)

对于 Flask,请使用 Talisman。 FlaskHerokuSSLify 文档倾向于使用 Talisman 而不是 SSLify,因为后者不再维护。

来自SSLify

<块引用>

扩展不再维护,更喜欢使用 Flask-Talisman 作为 Flask 安全指南鼓励这样做。

通过 pip 安装:

$ pip install flask-talisman

启动扩展(示例):

from flask import Flask
from flask_talisman import Talisman

app = Flask(__name__)
if 'DYNO' in os.environ:
    Talisman(app)

Talisman 默认启用 CSP(内容安全策略),仅允许加载来自同一域的资源。如果您想禁用它并处理影响:

Talisman(app, content_security_policy=None)

如果您不想禁用它,则必须设置 content_security_policy 参数以允许来自外部域的资源,例如 CDN。为此,请参阅 documentation