EFFは すべての場所でHTTPSを使用 をサイトで推奨しています。 Djangoを使用してログインページにHTTPSを実装することについて質問したとき、それは確かに 私が得た応答 :)でした
だから私はまさにそれをやろうとしている。 HTTPS専用に構成しようとしているDjango/nginxセットアップがあります。これは一種の動作しますが、問題があります。さらに重要なのは、httpsプレフィックスが表示されていても、本当にsecureであるかどうかです。
すべてのhttpページをhttpsにリダイレクトするようにnginxを構成しましたが、その部分は機能します。ただし... https://mysite.com/search/
というページに、検索フォーム/ボタンが付いているとします。 Djangoはフォームを処理し、http://mysite.com/search/results?term="foo"
であるresultsページにリダイレクトします。
このURLはブラウザーに送信され、ブラウザーはbackをnginxサーバーに送信します。nginxサーバーは、https
で始まるバージョンのページに永続的にリダイレクトします。 (少なくとも私はそれが起こっていることだと思います-確かにIEは私が安全でないページに行くことを警告し、次に戻って安全なページ:)
しかし、これは本当に安全ですか?または、少なくとも標準のHTTPS専用サイトと同じくらいのセキュリティがありますか? Djangoがhttp-prefix URLを送信し、誰かがセキュリティを危険にさらしているという事実ですか?はい、私が知る限り、https-prefixがあるページのみが返信されますが、それだけです'tfeelright :)このサイトが証明できるように、セキュリティはファンキーで、何か足りないものがあるのではないかと心配しています。
settings.py に行を入れます
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
cookieはHTTPS接続経由でのみ送信されます。さらに、おそらくSESSION_EXPIRE_AT_BROWSER_CLOSE=True
も必要です。古いバージョンのDjango(1.4未満))を使用している場合、セキュリティで保護されたCSRF Cookieの設定はありません。簡単な修正として、CSRF Cookieを安全にするには、セッションCookieはSESSION_COOKIE_SECURE=True
を編集することで安全です(Django/middleware/csrf.py
):
class CsrfViewMiddleware(object):
...
def process_response(self, request, response):
...
response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"], max_age = 60 * 60 * 24 * 7 * 52,
domain=settings.CSRF_COOKIE_DOMAIN,
secure=settings.SESSION_COOKIE_SECURE or None)
次に、nginxで、httpリクエストをhttpsにリダイレクトする書き換えルールが必要です。
server {
listen 80;
rewrite ^(.*) https://$Host$1 permanent;
}
Djangoのreverse
関数とurlテンプレートタグは相対リンクのみを返します。したがって、httpsページを表示している場合、リンクはhttpsサイトにとどまります。
最後に、(および私の元の応答ではこれを除外しました)、OS環境変数HTTPS
を'on'
に対して有効にする必要があります。Djangoは、完全に生成されたリンクにhttpsを付加します(例:HttpRedirectRequest
sなど)mod_wsgiを使用している場合は、次の行を追加できます。
os.environ['HTTPS'] = "on"
wsgiスクリプト に。 uwsgiを使用している場合は、コマンドラインスイッチ--env HTTPS=on
、またはuwsgi env = HTTPS=on
ファイルに行.ini
を追加することで、環境変数を追加できます。他に何も機能しない場合の最後の手段として、設定ファイルを編集してimport os
とos.environ['HTTPS'] = "on"
の行を含めることもできますが、これらも機能するはずです。
Wsgiを使用している場合は、環境変数wsgi.url_scheme
を'https'
に追加して、settings.py
に追加することができます。
os.environ['wsgi.url_scheme'] = 'https'
Vijayendra Bapteのコメント によるwsgiのアドバイス。
Django/http/__init__.py
を読むと、この環境変数の必要性を確認できます。
def build_absolute_uri(self, location=None):
"""
Builds an absolute URI from the location and the variables available in
this request. If no location is specified, the absolute URI is built on
``request.get_full_path()``.
"""
if not location:
location = self.get_full_path()
if not absolute_http_url_re.match(location):
current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http',
self.get_Host(), self.path)
location = urljoin(current_uri, location)
return iri_to_uri(location)
def is_secure(self):
return os.environ.get("HTTPS") == "on"
あの男のアドバイス を取り、nginxに行を追加してWebサーバーのHSTSヘッダーをオンにします。
add_header Strict-Transport-Security max-age=31536000;
これは、今後10年間のWebサイトがHTTPSのみを使用することをWebブラウザーに通知します。同じブラウザーからの今後の訪問に対して中間者攻撃がある場合(たとえば、ページのHTTPバージョンにリダイレクトするコーヒーショップの悪意のあるルーターにログオンする場合)、ブラウザーは覚えています。 HTTPSのみであることになっており、誤って情報をあきらめないようにします。ただし、これに注意してください。変更することはできません。後でドメインの一部をHTTPで提供することを決定できます(この行を削除してから10年が経過するまで)。したがって、事前に計画してください。たとえば、アプリケーションの人気がすぐに高まる可能性があり、手頃な価格でHTTPSを適切に処理できない大きなCDNを使用する必要がある場合、問題が発生する可能性があります。
また、弱いプロトコルを無効にしてください。ドメインを SSLテスト に送信して、潜在的な問題(短すぎるキー、TLSv1.2を使用していない、壊れたプロトコルを使用しているなど)を確認します。たとえば、nginxでは私が使用します:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
Http://から対応するhttps://ページにリダイレクトするのは間違ったアプローチです。ポート80を https://yourdomain.ext/ にリダイレクトするようにnginxを設定します
server {
listen 80;
rewrite ^/? https://$Host/ permanent;
}
または同様(近くの次のnginxマニュアルを確認してください)、ポート80(http)でアプリケーションを実行しないでください。したがって、ポート80での他のリクエストは404または類似のものに解決されます(アプリが安全になり、リンクが https://yourdomain.ext/ を指すhttpsでのみ実行されるようにカスタマイズしてください) 。次に、リスンポート443(https)でのみアプリを実行します。コード内で相対パスを使用すると、すべてが完全なhttps://パスに解決され、httpからhttpsへのバウンスを回避できるため、安全です。
さらに、nginxから HSTS-Header を送信して、クライアント(ブラウザ)にHTTPSのみを使用することを示す必要があります。
add_header Strict-Transport-Security max-age=31536000;
一般的な設定では、httpsトラフィックをWebサーバー(つまりNginx)からDjangoアプリを実行しているローカルhttpサーバーに転送します。
この場合、SECURE_PROXY_SSL_HEADER
設定を使用する方が簡単です(Django 1.4以降で使用可能)。
https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADER
私が探しているのはDjango http
をhttps
に書き換えるミドルウェアです。 SO に関するこの質問では、1つの回答が thisミドルウェア を指しています。おそらく、独自のミドルウェアを作成しますが、それは簡単なはずです(SOについての焦点を絞った質問は、開始に支援が必要な場合、正しい方向に向けられます)。
受け入れられた回答で説明されているように、ほとんどの場合、Apacheまたは何かをhttpsにリダイレクトするように設定できます。できれば、パフォーマンスとDjangoの外部で提供されるファイルの方が良いでしょう。
しかし、できない場合、またはデバッグを行いたい場合は、Django最近(1.8)がhttps-redirectsの1つとしてSecurityMiddleware
を導入したことを指摘しておきますいくつかの機能。
詳細は ドキュメント を参照してください。基本的に、Django.middleware.security.SecurityMiddleware
とセットSECURE_SSL_REDIRECT = True
。
(受け入れられた回答で言及されているヘッダーは、このミドルウェアによっても設定できます。)
Djangoのいずれかを生成するには、
https://domain/path
はhttps:
スキームとリンクし、//domain/path
スキームなしのリンク(ブラウザーはこれらを現在開いているページと同じスキームを持つものとして解釈します)、または/path
リンクはスキームもドメインもありません(ブラウザはこれらが現在指しているページと同じスキームとドメインを持つと解釈します)。