Heroku(Cedarスタック)にpython/Djangoアプリがあり、https経由でのみアクセスできるようにしたいと考えています。 「ssl piggyback」オプションを有効にして、https経由で接続できるようにしました。
しかし、httpアクセスを無効にする、またはhttpsにリダイレクトする最良の方法は何ですか?
@CraigKerstiensと@allanleiからの回答を、私がテストし、機能することを確認したものに結合します。 Herokuは、リクエストがsslの場合、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は、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
@CraigKerstiensの回答がrequest.is_secure()
がHerokuのリバースプロキシの背後にあり、「修正」されていない場合、常にFalse
を返すことを考慮に入れているかどうかはわかりません。私の記憶が正しければ、これによりHTTPリダイレクトループが発生します。
Djangoをgunicornで実行している場合、別の方法は、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-header
_を設定することで、request.is_secure()
はhttpsリクエストでTrue
を適切に返します。 Gunicorn Config を参照してください。
これで、@ CraigKerstiensのミドルウェアは、アプリ内のrequest.is_secure()
への呼び出しを含め、正しく機能します。
注:Djangoにも同じ構成設定呼び出し_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フラスコ-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)