如何使Heroku上的Python只有https?

我有Heroku(雪松堆栈)上的python / django应用程序,并希望通过https访问它。 我已经启用了“ssl piggyback”选项,并可以通过https连接到它。

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

将来自@CraigKerstiens和@allanlei的答案合并成我已经testing过的东西,并validation可以正常工作。 当请求是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) 

Django 1.8将对非HTTPSredirect(从django-secure集成)提供核心支持:

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

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

不知道@ CraigKerstiens的答案考虑到了,如果在Heroku的反向代理之后, request.is_secure()总是返回False ,而不是“fixed”。 如果我没有记错,这将导致HTTPredirect循环。

如果你使用gunicorn运行Django,另一种方法是在gunicorn的configuration文件中添加以下内容

 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 。 见Gunicornconfiguration 。

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

注:Django也具有相同的configuration设置调用SECURE_PROXY_SSL_HEADER ,但是在dev版本中。

你的应用程序使用了什么框架? 如果你使用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) 

如果你使用的是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)