HTTPの代わりにHTTPSを使用してユーザーに自分のページへのアクセスを強制するにはどうすればよいですか?


137

HTTPSページ(PHP on Apache)として強制的にアクセスさせたいページが1つだけあります。ディレクトリ全体にHTTPSを必要とせずにこれを行うにはどうすればよいですか?または、HTTPページからHTTPSページにフォームを送信すると、HTTPではなくHTTPSでフォームが送信されますか?

これが私の例です:

http://www.example.com/some-page.php

次の方法でのみアクセスできるようにします。

https://www.example.com/some-page.php

確かに、このページへのすべてのリンクをHTTPSバージョンに向けることができますが、それによって、愚か者が故意にHTTPを介してアクセスするのを止めることはできません...

私が思ったのは、PHPファイルのヘッダーにリダイレクトを入れて、HTTPSバージョンにアクセスしていることを確認することです。

if($_SERVER["SCRIPT_URI"] == "http://www.example.com/some-page.php"){
  header('Location: https://www.example.com/some-page.php');
}

しかし、それは正しい方法ではありませんか?



3
すべてのページでSSLを必要としない理由はありますか?
タハーン島

回答:


177

私が以前にやった方法は基本的にあなたが書いたものに似ていますが、ハードコードされた値はありません:

if($ _ SERVER ["HTTPS"]!= "オン")
{
    header( "場所:https://"。$ _SERVER ["HTTP_HOST"]。$ _SERVER ["REQUEST_URI"]);
    出口();
}

15
リダイレクト後にスクリプトが確実に終了するように、exit()を呼び出すのを忘れていました。私は通常それをrequireSSL()と呼ばれる関数でラップします。暗号化したいページの上部でこれを呼び出すことができます。
Jesse Weigert、

31
(empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on")PHP通知を修正するためにifを変更します。
dave1010 2013年

$_SERVER[]変数はユーザーの介入に対して変更可能/脆弱ではありませんか?
Arian Faurtosh、2014年

@ArianFaurtoshソース?
John

3
@ArianFaurtoshの一部はのようHTTP_X_FORWARDEDにクライアントヘッダーから抽出され、操作できますが、HTTPSまたはのようSERVER_PORTにWebサーバーから直接設定されるため、通常は安全です。
Mahn

46

Apacheのディレクティブとmod_rewriteでそれを行うことができます:

<Location /buyCrap.php>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</Location>

必要に応じて、正規表現を使用して、時間の経過とともにLocationをよりスマートにすることができます。


6
これはどこに置きますか?.htaccessファイル?

1
REQUEST_URIに「クエリ文字列」が含まれていませんか(?page = 1&id = 41など)。私がアクセスしようもしそうならそれは... Apacheのマニュアルが言うことだsite.com/index.php?page=1&id=12私がリダイレクトされますsite.com/index.phpを
ロルフ

2
Apacheドキュメントから:REQUEST_URIリクエストされたURIのパスコンポーネント( "/index.html"など)。これは特に、QUERY_STRINGという名前の独自の変数として使用できるクエリ文字列を除外します。したがって、REQUEST_URIの後にQUERY_STRINGを追加する必要があります
Rolf

2
また、リダイレクトするために[R]フラグを追加する必要があります
Rolf

40

クライアントに、HTTP Strict Transport Security(HSTS)ヘッダーを使用して常にHTTPSを要求するように強制する必要があります

// Use HTTP Strict Transport Security to force client to use secure connections only
$use_sts = true;

// iis sets HTTPS to 'off' for non-SSL requests
if ($use_sts && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
    header('Strict-Transport-Security: max-age=31536000');
} elseif ($use_sts) {
    header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
    // we are in cleartext at the moment, prevent further execution and output
    die();
}

HSTSは最新のほとんどのブラウザーでサポートされていますが、ユニバーサルではないことに注意してください。したがって、上記のロジックは、サポートに関係なく、ユーザーがHTTPで終了する場合は手動でユーザーをリダイレクトし、HSTSヘッダーを設定して、可能であればさらにクライアント要求がブラウザーによってリダイレクトされるようにします。


他の回答にこのヘッダーが含まれていないことに驚いていますが、それは非常に重要です...それらの2つを組み合わせるための落とし穴はありますか?
ケイサー2013

いいえ... HTTPSが常に必要な場合は、とにかくそのヘッダーを設定できます。リダイレクトを行う前と後で設定するのは、ちょっと冗長です。互換性をより正確に説明するために、上記の回答を修正しました。
Jacob Swartwood 2013

1
(元のコメントを編集中)「1ページだけ」という特定の要件に気づきませんでした。HSTSはすべてのページに適用されます。私の答えは技術的に正しくありません。
Jacob Swartwood 2013

4
参考までに、標準のRFC 6797セクション7.2は、「HSTSホストは、非セキュアなトランスポートを介して伝達されるHTTP応答にSTSヘッダーフィールドを含めてはならない(MUST NOT)」と述べています。そのため、リクエストが通常のhttpの場合は送信する必要はありません。ブラウザが標準に従っている場合は、無視する必要があります。
フランクフォルテ

1
@markがMITMであり、Webサイトにこのヘッダーがない場合は、構成されたセッションがhttpに移動することを許可し、人々が詳細を入力しても、おそらく気付かず、リダイレクトが役に立たない(man in真ん中はhttps経由でサイトに接続し、httpとして表示します。このヘッダーを使用すると、クライアント側でHTTPSが強制されます。最近のWPA2 WiFiセキュリティ脆弱性のため、これは特に重要です。
Rudiger

19

.htaccessファイルを作成して追加しました:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

シンプル!


9
// Force HTTPS for security
if($_SERVER["HTTPS"] != "on") {
    $pageURL = "Location: https://";
    if ($_SERVER["SERVER_PORT"] != "80") {
        $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
    } else {
        $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
    }
    header($pageURL);
}

8

ロードバランサーの背後で実行するときに、このようなことをしなければなりませんでした。ハットチップhttps://stackoverflow.com/a/16076965/766172

function isSecure() {
    return (
        (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
     || $_SERVER['SERVER_PORT'] == 443
     || (
            (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
         || (!empty($_SERVER['HTTP_X_FORWARDED_SSL'])   && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on')
        )
    );
}

function requireHTTPS() {
    if (!isSecure()) {
        header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], TRUE, 301);
        exit;
    }
}

6

PHPの方法:

$is_https=false;
if (isset($_SERVER['HTTPS'])) $is_https=$_SERVER['HTTPS'];
if ($is_https !== "on")
{
    header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
    exit(1);
}

Apache mod_rewriteの方法:

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

SSLの要件を上書きしたい場合があるので、PHPの方法を使用します。たとえば、APIへのローカルアクセスやMozilla Thunderbirdの自動構成などのようなもの
Jay

PHPの方法は完全に機能します。
Moxet Jan

5

http://www.besthostratings.com/articles/force-ssl-htaccess.html

ユーザーがセキュリティで保護された接続でサイトを閲覧していることを確認する必要がある場合があります。ユーザーを常に安全な接続(https://)にリダイレクトする簡単な方法は、次の行を含む.htaccessファイルを使用して実現できます。

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]

.htaccessはWebサイトのメインフォルダに配置する必要があることに注意してください。

特定のフォルダにHTTPSを強制したい場合は、次のように使用できます。

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteCond %{REQUEST_URI} somefolder 
RewriteRule ^(.*)$ https://www.domain.com/somefolder/$1 [R,L]

.htaccessファイルは、HTTPSを強制する必要があるフォルダに配置する必要があります。


5

わかりました。今、これについてはたくさんありますが、「安全な」質問に答える人はいません。私にとって、安全でないものを使用することはばかげています。

餌として使わない限り。

$ _SERVERの伝播は、方法を知っている人の意向で変更できます。

また、Sazzad Tushar Khanとthebigjcが述べたように、httaccessを使用してこれを行うこともできます。これを含む多くの回答があります。

追加するだけです:

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/$1 [R,L]

.httaccessにあるものの最後まで。

それでも、これらの2つのツールでできるほど安全ではありません。

残りは簡単です。不足している属性がある場合...

if(empty($_SERVER["HTTPS"])){ // SOMETHING IS FISHY
}

if(strstr($_SERVER['HTTP_HOST'],"mywebsite.com") === FALSE){// Something is FISHY
}


また、httaccessファイルを更新し、以下を確認するとします。

if($_SERVER["HTTPS"] !== "on"){// Something is fishy
}

チェックできる変数はもっとたくさんあります。

HOST_URI (チェックする静的な属性がある場合)

HTTP_USER_AGENT (同じセッションの異なる値)

イムが言っていることはすべて、答えが組み合わせにあるとき、どちらか一方だけで解決しないことです。

もっとhttaccess情報を書き換えるためにdocs->参照http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

ここではいくつかのスタックを- > フォースSSL / HTTPSの.htaccessとのmod_rewriteを使用
して
の完全なURLを取得します現在のページ(PHP)


2
しかし、今私は次のエラーを受け取ります:ERR_TOO_MANY_REDIRECTS。どうすれば修正できますか?
Pathros

3

使用する$_SERVER['HTTPS']ことがあれば教えてSSL、および適切な場所へのリダイレクトでない場合。

また、フォームを表示するページはHTTPS経由でフィードする必要はありません。最も必要なのはポストバックURLです。

編集:はい、以下で指摘するように、プロセス全体をHTTPSで実行するのが最善です。それははるかに安心です-私は投稿が最も重要な部分であることを指摘していました。また、Cookieが安全に設定されているため、SSL経由でのみ送信されるように注意する必要があります。mod_rewriteソリューションも非常に気の利いたものであり、自分のWebサイトで多くのアプリケーションを保護するために使用しました。


フォーム自体がhttpsである必要はないことは事実ですが、これを知らない大多数の人にとっては良い考えです。フォームを送信しようとしていて、ロックアイコンが表示されていないことに気付いた場合、フォームが安全でないと誤って判断する可能性があります。
Graeme Perrow

1
@Graeme:さらに、フォームがhttps経由で送信されることを誰も確信できません。フォーム全体(httpを介して表示される)は偽の可能性があり、不明なサイトまたはhttpクリアテキストサイトに送信します。Httpsは暗号化だけではなく、サーバーの認証も行います。
Olaf Kock

3

使用htaccess

#if domain has www. and not https://
  RewriteCond %{HTTPS} =off [NC]
  RewriteCond %{HTTP_HOST} ^(?i:www+\.+[^.]+\.+[^.]+)$
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307]

#if domain has not www.
  RewriteCond %{HTTP_HOST} ^([^.]+\.+[^.]+)$
  RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307]

1

同じページでHTTPとHTTPSを混在させないでください。HTTPを介して提供されるフォームページがある場合、データの送信について不安になります-送信がHTTPSとHTTPのどちらで行われるかを確認するには、ソースの表示を実行してそれを探します。

送信リンクとともにHTTPS経由でフォームを提供することは、利点にとってそれほど大きな変更ではありません。


1

Apacheまたは.htaccessファイルをサポートするLiteSpeedのようなものを使用している場合、次のことができます。.htaccessファイルがない場合は、ルートディレクトリ(通常はindex.phpがある場所)に新しい.htaccessファイルを作成する必要があります。次に、これらの行を.htaccessの最初の書き換えルールとして追加します。

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

すべての書き換えルールに対して.htaccessで「RewriteEngine On」という命令を1回だけ必要とするので、すでにそれがある場合は、2行目と3行目をコピーします。

これがお役に立てば幸いです。


これは私のために働いたものであり、私がZend 2のようなフレームワーク上の自分のスクリプトで使用しているものです-私は反対票を理解していません。
アントニオ

回答が1年以上前に投稿された@MatHatrikからの回答と実質的に同じであるため、反対票を投じた可能性がありますか?
Wilt

1

これを使用するだけでは十分ではありません。

if($_SERVER["HTTPS"] != "on")
{
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

httpコンテンツ(外部のhttp画像ソースなど)がある場合、ブラウザーは潜在的な脅威を検出します。コード内のすべてのrefとsrcがhttpsであることを確認してください


1

$ _SERVER [HTTPS]のステータスをチェックする多くの解決策を講じ てきましたが、オンまたはオフなどに設定または設定されないことがあり、スクリプトが内部ループリダイレクトを引き起こすため、信頼できないようです。

サーバーが$ _SERVER [SCRIPT_URI]をサポートしている場合、これが最も信頼できるソリューションです。

if (stripos(substr($_SERVER[SCRIPT_URI], 0, 5), "https") === false) {
    header("location:https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
    echo "<meta http-equiv='refresh' content='0; url=https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]'>";
    exit;
}

インストールによっては、サーバーが$ _SERVER [SCRIPT_URI]をサポートしていない場合がありますが、サポートしている場合は、このスクリプトを使用することをお勧めします。

ここで確認できます:なぜ一部のPHPインストールには$ _SERVER ['SCRIPT_URI']があり、他にはないのですか


1

IISを使用している場合は、この行をweb.configに追加すると役立ちます。

<httpProtocol>
    <customHeaders>
        <add name="Strict-Transport-Security" value="max-age=31536000"/>
    </customHeaders>
</httpProtocol>
<rewrite>
    <rules>
        <rule name="HTTP to HTTPS redirect" stopProcessing="true">
              <match url="(.*)" />
              <conditions>
                 <add input="{HTTPS}" pattern="off" ignoreCase="true" />
              </conditions>
              <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
         </rule>
    </rules>
</rewrite>

完全なサンプルファイル

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <add name="Strict-Transport-Security" value="max-age=31536000"/>
             </customHeaders>
        </httpProtocol>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                      <match url="(.*)" />
                      <conditions>
                         <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                      </conditions>
                      <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                 </rule>
            </rules>
       </rewrite>
   </system.webServer>
</configuration>

この質問では、特にIISではなくApacheについて質問します。
クエンティン

1
A)タグ付けされていないapache。Apacheは引用符で囲まれています。B)一般的なapacheとは何の関係もない一般的な質問。Webサーバーをサポートする複数のphpに適用可能
Tschallacka

0

あなたはセキュリティ上の理由からすべきではありません。特にここでクッキーが使われている場合は。これにより、Cookieベースのリプレイ攻撃に広く開放されます。

どちらの方法でも、Apache制御ルールを使用して調整する必要があります。

次に、HTTPSが有効になっているかどうかをテストし、必要に応じて必要に応じてリダイレクトできます。

FORM POST(取得なし)のみを使用して有料ページにリダイレクトし、POSTなしのページへのアクセスは他のページにリダイレクトする必要があります。(これは、ホットジャンプする人々を捕まえるでしょう。)

http://joseph.randomnetworks.com/archives/2004/07/22/redirect-to-ssl-using-apaches-htaccess/

開始するには良い場所ですが、これ以上提供しないことをお詫びします。ただし、SSLを使用してすべてを強制する必要があります。

それは過保護ですが、少なくともあなたは心配が少なくなります。


0

多分これはあなたを助けることができます、あなた、それは私が私のウェブサイトのためにした方法です、それは魅力のように機能します:

$protocol = $_SERVER["HTTP_CF_VISITOR"];

if (!strstr($protocol, 'https')){
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

0

これを行うためにPHPを使用したい場合、この方法は私にとって本当にうまくいきました:


<?php

if(!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != "on") {
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"], true, 301);
    //Prevent the rest of the script from executing.
    exit;
}
?>

$ _SERVERスーパーグローバル配列のHTTPS変数をチェックして、「on」に等しいかどうかを確認します。変数がonと等しくない場合。


-1

私はこのスクリプトを使用しましたが、サイト全体でうまく機能します。

if(empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "off"){
    $redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    enter code hereheader('HTTP/1.1 301 Moved Permanently');
    header('Location: ' . $redirect);
    exit();
}

-2
<?php 
// Require https
if ($_SERVER['HTTPS'] != "on") {
    $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
    header("Location: $url");
    exit;
}
?>

簡単です。

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