如何只在Heroku https上制作python?

Kri*_*ian 55 python django ssl https heroku

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

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

Kri*_*ian 65

将@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)
Run Code Online (Sandbox Code Playgroud)

  • 答案现在是[app on github](https://github.com/rdegges/django-sslify) (29认同)
  • 在这种情况下,请记住将此添加到设置中以让django知道请求是安全的:SECURE_PROXY_SSL_HEADER =('HTTP_X_FORWARDED_PROTO','https') (4认同)
  • 作为旁注,如果将DEBUG设置为True,则不起作用.花了一个小时搞清楚这一个,所以希望这能节省一些时间. (3认同)

sha*_*iao 50

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

SECURE_SSL_REDIRECT = True # [1]
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
Run Code Online (Sandbox Code Playgroud)

为了SECURE_SSL_REDIRECT处理你必须使用SecurityMiddleware:

MIDDLEWARE = [
    ...
    'django.middleware.security.SecurityMiddleware',
]
Run Code Online (Sandbox Code Playgroud)

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

  • sslify的作者确认[这里](https://github.com/rdegges/django-sslify/issues/31)@dfrankow是正确的,sslify对于Django来说已经过时了> = 1.8 (10认同)

All*_*Lei 13

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

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

secure_scheme_headers = {
    'X-FORWARDED-PROTO': 'https'
}
Run Code Online (Sandbox Code Playgroud)

在Procfile中运行类似的东西

web: python manage.py run_gunicorn -b 0.0.0.0:$PORT -c config/gunicorn.conf
Run Code Online (Sandbox Code Playgroud)

通过设置gunicorn secure-scheme-header,request.is_secure()将正确返回Truehttps请求.见Gunicorn Config.

现在@ CraigKerstiens的中间件可以正常工作,包括request.is_secure()你的应用程序中的任何调用.

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

  • django SECURE_PROXY_SSL_HEADER设置现在可以在主线中使用(当然可以在1.6,也许更早). (2认同)

Cra*_*ens 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)
Run Code Online (Sandbox Code Playgroud)


Rya*_*yan 6

2020年更新:

如果您使用 Flask,我会推荐以下内容:

@app.before_request
def before_request():
    if 'DYNO' in os.environ:
        if request.url.startswith('http://'):
            url = request.url.replace('http://', 'https://', 1)
            code = 301
            return redirect(url, code=code)
Run Code Online (Sandbox Code Playgroud)

以上在 Heroku 上效果很好,并允许您http在本地开发中使用heroku local.

Flask-SSLify 不再维护,也不再受到 Flask 社区的正式支持。

2014 原始答案:

如果您使用的是 Flask,这很有效:

  1. 执行“pip install flask-sslify”

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

  1. 包括以下几行:
from flask_sslify import SSLify
if 'DYNO' in os.environ: # only trigger SSLify if the app is running 
on Heroku
    sslify = SSLify(app)
Run Code Online (Sandbox Code Playgroud)