web-dev-qa-db-ja.com

Heroku httpsでのみpythonを作成する方法は?

Heroku(Cedarスタック)にpython/Djangoアプリがあり、https経由でのみアクセスできるようにしたいと考えています。 「ssl piggyback」オプションを有効にして、https経由で接続できるようにしました。

しかし、httpアクセスを無効にする、またはhttpsにリダイレクトする最良の方法は何ですか?

55
Kristian

@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)
64
Kristian

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

48
shangxiao

@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バージョンにあります。

13
Allan Lei

アプリケーションにどのフレームワークを使用していますか? 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)
6
CraigKerstiens

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)
4
Ryan