.htaccessとmod_rewriteを使用してSSL / httpsを強制する


回答:


438

Apacheの場合、を使用mod_sslしてSSLを強制することができますSSLRequireSSL Directive

このディレクティブは、現在の接続でHTTP over SSL(つまりHTTPS)が有効になっていない限り、アクセスを禁止します。これは、SSL対応の仮想ホストまたはディレクトリ内で、保護する必要のあるものを公開する構成エラーを防ぐために非常に便利です。このディレクティブが存在する場合、SSLを使用していないすべての要求が拒否されます。

ただし、httpsへのリダイレクトは行われません。リダイレクトするにmod_rewriteは、.htaccessファイルで次を試してください

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

またはで与えられた様々なアプローチのいずれか

プロバイダーが.htaccessを無効にしている場合に備えて、これをPHP内から解決することもできます(要求されたため、そうではありませんが)

if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    if(!headers_sent()) {
        header("Status: 301 Moved Permanently");
        header(sprintf(
            'Location: https://%s%s',
            $_SERVER['HTTP_HOST'],
            $_SERVER['REQUEST_URI']
        ));
        exit();
    }
}

1
現在、httpトラフィックとhttpsトラフィックが混在しているため、これは状況に最適です。私たちの管理領域では、サイトの残りの部分をhttpに保ちながら.htaccessスクリプトをポップしました。
Michael J. Calkins 2014

1
mod_rewriteメソッドを使用すると、httpsに送信されますが、「ページが正しくリダイレ​​クトされていません」というエラーが表示されます。
チェコ語2014年

11
フォローアップ:同様の問題が発生している場合は、サーバーとHTTP変数を確認してください。サーバーでプロキシを使用している場合は、%{HTTP:X-Forwarded-Proto}または%{HTTP:X-Real-Port}変数を使用して、SSLがオンになっているかどうかを確認できます。
チェコ語2014年

8
プロキシ(CloudFlareOpenshift)の背後で実行されているサーバーでリダイレクトループが発生した場合は、この回答がそのケースでも機能する解決策を参照してください。
ラフィネッセ2015

4
@GTodorov-スペースを削除すると、リライタールが壊れました。リライターに関する私の(限られた)知識から、構文はRewriteRule <input-pattern> <output-url>です。したがって、スペースはそこにある必要があり、シングル^は「すべての入力URLに一致する」と言うだけです。
Sphinxxx 2016年

54

mod_rewriteプロキシされたサーバーとプロキシされていないサーバーの両方でうまく機能するソリューションを見つけました。

あなたが使用している場合にCloudFlare、AWS弾性ロードバランシング、Herokuの、OpenShiftまたは任意の他のクラウド/ PaaSのソリューションを、あなたが経験しているリダイレクトループを通常のHTTPSリダイレクトで、代わりに次のスニペットを試してみてください。

RewriteEngine On

# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on

# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

これは素晴らしいthxです!しかし、おそらくそれはポスト条件を追加する必要がありますか?するRewriteCondの%{REQUEST_METHOD} ^ POST $!
Aleksej

@Aleksej確かに、これは暗号化されていないPOSTリクエストを壊します。しかし、これは良いことだと思います。このようにして、人々は何かが間違っていることに気づくでしょう。サービスを適切に使用する方法を通知するページにリダイレクトするのが最良の方法だと思います。
ラフィネッセ2018年

ドゥ@raphinesseあなたはこの質問の答えを知っている:stackoverflow.com/questions/51951082/...
RRN

36

PHPソリューション

Gordonの非常に包括的な答えから直接借りて、あなたの質問はHTTPS / SSL接続の強制においてページ固有であることに言及していることに注意します。

function forceHTTPS(){
  $httpsURL = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  if( count( $_POST )>0 )
    die( 'Page should be accessed with HTTPS, but a POST Submission has been sent here. Adjust the form to point to '.$httpsURL );
  if( !isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS']!=='on' ){
    if( !headers_sent() ){
      header( "Status: 301 Moved Permanently" );
      header( "Location: $httpsURL" );
      exit();
    }else{
      die( '<script type="javascript">document.location.href="'.$httpsURL.'";</script>' );
    }
  }
}

次に、PHPを介して強制的に接続するこれらのページの上部に近い場所で、require()この(およびその他の)カスタム関数を含む集中型ファイルを作成し、forceHTTPS()関数を実行します。

HTACCESS / mod_rewriteソリューション

私はこの種のソリューションを個人的には実装していません(単純にするために、上記のようなPHPソリューションを使用する傾向がありました)が、少なくとも以下は良い出発点になるかもしれません。

RewriteEngine on

# Check for POST Submission
RewriteCond %{REQUEST_METHOD} !^POST$

# Forcing HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# Forcing HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

好奇心から、なぜRewriteCond %{REQUEST_METHOD} !^POST$
デポロ2013年

12
POSTパラメータはリダイレクトで保持されないためです。すべてのPOST送信が安全であることを確認したい場合は、その行を省略できます(保護されていないPOST送信は無視されます)。
ルークスティーブンソン2013年

@Lucanos-POST時にhttpまたはhttpsへのリダイレクトを強制しないRewriteCondの記述方法 私の.htaccessは特定の特定のページにHTTPSを強制し、残りをHTTPに強制します。ただし、HTTPSページには、私のWebルートに送信するフォームがあります。フォームはアクションURLをHTTPSとして指定します。ただし、WebルートはHTTPSを強制するように指定されているページではないため、.htaccessはリダイレクトを強制します。つまり、POST変数が失われます。POSTでのリダイレクトを防ぐにはどうすればよいですか?
StackOverflowNewbie 14

1
@StackOverflowNewbie:この行RewriteCond %{REQUEST_METHOD} !^POST$により、POST 送信がこれらのリダイレクトの影響を受けないようにする必要があります。
ルークスティーブンソン

このPHPバージョンが好きです。POSTを考慮し、ヘッダーが既に送信されている場合は処理が向上するため、はるかに優れています。
TheStoryCoder 2016

10

Mod-rewriteベースのソリューション:

htaccessで次のコードを使用すると、すべてのhttpリクエストがhttpsに自動的に転送されます。

RewriteEngine on

RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

これにより、非wwwおよびwww httpリクエストがwwwバージョンのhttpsにリダイレクトされます。

別のソリューション(Apache 2.4 *)

RewriteEngine on

RewriteCond %{REQUEST_SCHEME}::%{HTTP_HOST} ^http::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

2.4以降、%-{REQUEST_SCHEME}変数がmod-rewriteに追加されたため、これはApacheの下位バージョンでは機能しません。


9

ディレクトリの深さを越えて複数の.htaccessファイルを使用する場合 Apacheには最悪の継承ルールがあることを指摘しておきます。2つの重要な落とし穴:

  • デフォルトでは、最も深い.htaccessファイルに含まれているルールのみが実行されます。RewriteOptions InheritDownBeforeこれを変更するには、ディレクティブ(または同様の)を指定する必要があります。(質問を参照)
  • パターンは、指定されたルールの.htaccessファイルを含む上位ディレクトリではなく、サブディレクトリに対するファイルパスに適用されます。(議論を参照)

つまり、サブディレクトリで他の.htaccessファイルを使用すると、Apache Wikiで提案されているグローバルソリューションは機能しませ。私は次のような修正バージョンを作成しました。

RewriteEngine On
# This will enable the Rewrite capabilities

RewriteOptions InheritDownBefore
# This prevents the rule from being overrided by .htaccess files in subdirectories.

RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [QSA,R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e.  http://www.example.com/foo/ to https://www.example.com/foo/

0

シンプルで簡単、以下を追加するだけ

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

これは、インターネット全体の人々がhttpsを強制するために行うようにと言っていることとほとんど同じです。しかし、私がそれを行うたびに、私のウェブサイト全体が禁止されたり、閲覧する許可がありません。そのようなもの...私は何を間違っているのですか?これについて質問をする前に、あなたが何か考えがあるかどうか知りたいだけです。
2018

同様の問題があり、https.confファイルにルールを適用する必要がありました。以下の私の答えを参照してください。
Risteard

-1

このコードは私のために働きます

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

-1

シンプルなもの:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.example\.com)(:80)? [NC]
RewriteRule ^(.*) https://example.com/$1 [R=301,L]
order deny,allow

URLをexample.comに置き換えます


番号!サイトのURLは動的である必要があります。
Amir Savand

-1

Apache .htaccessでSSLを強制するために使用できます

SSLOptions +StrictRequire
SSLRequireSSL

リダイレクトの場合、上記の答えは正しいです


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.