web-dev-qa-db-ja.com

Flask httpsの代わりにhttp URLを生成するurl_for

私は使っている url_forユーザーがログアウトしたときにリダイレクトURLを生成するには:

return redirect(url_for('.index', _external=True))

ただし、ページをhttps接続に変更すると、url_forはまだ私に与えますhttp

私は明示的にurl_forを追加して、URLの先頭にhttpsを追加します。

変更方法を教えてください。 Flask docs、運なし。

37
Blaise

Flask 0.10では、_url_for_をラップするよりもはるかに優れたソリューションが利用できます。 https://github.com/mitsuhiko/flask/commit/b5069d07a24a3c3a54fb056aa6f4076a0e7088c7 、__scheme_パラメーターが追加されたため、次のことができます。

_url_for('secure_thingy',
        _external=True,
        _scheme='https',
        viewarg1=1, ...)
_

__scheme_はURLスキームを設定し、_https://.._ではなく_http://_のようなURLを生成します。ただし、デフォルトではFlaskは(ホストまたはスキームなしで)パスのみを生成するため、__external=True_から_/secure_thingy_に進むには_https://example.com/secure_thingy_を含める必要があります。 。


ただし、代わりにWebサイトをHTTPSのみにすることを検討してください。一部の「安全な」ルートに対してのみHTTPSを部分的に適用しようとしているようですが、https-URLを確認できません安全なページにリンクしているページが暗号化されていない場合は変更されません。これは 混合コンテンツ に似ています。

49

すべての呼び出しでurl_forを設定するのではなく、すべてのサーバー生成URL(_schemeおよびredirect)のURLスキームに影響を与えたい場合、「正しい」答えは、このスニペットのようにWSGIミドルウェアを使用することです。 http://flask.pocoo.org/snippets/35/

これFlaskバグ は、それが好ましい方法であることを確認しているようです。)

基本的に、WSGI環境にenviron['wsgi.url_scheme'] = 'https'がある場合、url_forhttps: URLを生成します。

サーバーが通常のHTTPでサーバーと通信するElastic Beanstalkロードバランサーの背後にデプロイされたため、http://からurl_for URLを取得していました。私のソリューション(Elastic Beanstalkに固有)は次のようなものでした(上記のリンクから抜粋したものです):

class ReverseProxied(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        scheme = environ.get('HTTP_X_FORWARDED_PROTO')
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        return self.app(environ, start_response)

app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)

その中のElastic Beanstalk固有の部分はHTTP_X_FORWARDED_PROTOです。他の環境では、外部URLにhttpsが含まれているかどうかを判断する他の方法があります。常にHTTPSを使用する場合は、無条件にenviron['wsgi.url_scheme'] = 'https'を設定できます。

PREFERRED_URL_SCHEMEはこれを行う方法ではありません。 リクエストの進行中は無視されます です。

27
aldel

私はurl_for引数で受け入れられた答えを試しましたが、 PREFERRED_URL_SCHEME config変数を使用してhttpsに設定する方が簡単であることがわかりました:

app.config.update(dict(
  PREFERRED_URL_SCHEME = 'https'
))

すべてのurl_for呼び出しに追加する必要がないためです。

23
dajobe

Nginxのようなリバースプロキシを介してWebサイトにアクセスしている場合、Flask=はスキームがHTTPであることを正しく検出します。

Browser -----HTTPS----> Reverse proxy -----HTTP----> Flask

最も簡単な解決策は、X-Forwarded-Protoヘッダー。 Flaskは自動的にこのヘッダーを検出し、それに応じてスキームを管理します。 の詳細な説明がFlaskドキュメントの下にありますProxy Setupsセクション 。たとえば、Nginxを使用する場合、locationブロックに次の行を追加する必要があります。

proxy_set_header   X-Forwarded-Proto    $scheme;

他の言及したように、プロキシの構成を変更できない場合は、ドキュメントに記載されているように、werkzeug ProxyFixを使用するか、独自の修正をビルドできます。 http://flask.pocoo .org/docs/0.12/deploying/wsgi-standalone /#proxy-setups

13

url_for()の呼び出しごとに_schemeを設定するのは非常に面倒で、PREFERRED_URL_SCHEMEは機能しないようです。ただし、WSGIレベルでのリクエストの想定スキームをいじると、Flaskが常にHTTPS URLを構築するように説得することに成功したようです。

def _force_https(app):
    def wrapper(environ, start_response):
        environ['wsgi.url_scheme'] = 'https'
        return app(environ, start_response)
    return wrapper

app = Flask(...)

app = _force_https(app)
8
cvrebert