web-dev-qa-db-ja.com

$ _SERVER ['REQUEST_SCHEME']は信頼できますか?

私は最近、URLリクエストがサーバーに提供されるプロトコルを適切に決定する方法を探していました。

parse_url() を介して $_SERVER スーパーグローバル変数、そしてこれを見つけました:

<?php
header('Content-Type: text/plain');

print_r($_SERVER);
?>

出力:

[REQUEST_SCHEME] => http

ただし、 php.net またはGoogleで見つけることができませんでした。しかし、私は this の質問を見つけることができました。 Q#1:If $_SERVER['REQUEST_SCHEME']文書化されていなかったので、おそらく信頼できないか、信頼できるか?

使っています VC9 PHP 5.4.14 TS開発用ウィンドウの下。しかし、私の作品はubuntuの下にあります。 Q#2:このプロパティはubuntu linuxでも利用可能ですか?

35
BlitZ

信頼性があることを証明するのは難しいですが、信頼性がないことを証明するのは簡単です(うまくいかないケースを提供できれば)。そして、IIS 7.0 + PHP 5.では動作しないため、信頼できないことを証明できます。

33
invisal

REQUEST_SCHEME環境変数は Apache mod_rewriteページ に記載されています。ただし、Apache 2.4まで使用できませんでした。

Apache 2.2しか持っていないので、環境変数を作成しました。 .htaccessファイルの先頭に次を追加しました。

RewriteEngine on

# Set REQUEST_SCHEME (standard environment variable in Apache 2.4)
RewriteCond %{HTTPS} off
RewriteRule .* - [E=REQUEST_SCHEME:http]

RewriteCond %{HTTPS} on
RewriteRule .* - [E=REQUEST_SCHEME:https]

今、私は使用することができます

  • %{ENV:REQUEST_SCHEME}他の書き換え条件とルール
  • $_SERVER['REQUEST_SCHEME'] in my PHP code

どこでも余分な面倒な条件チェックを行う必要はありません。また、私のPHPコードは上位互換性があります。Apacheがアップグレードされると、.htaccessファイルを変更できます。

これをWindows環境にどのように適用するかわかりません。これはおそらく分散コードには適したソリューションではありませんが、私のニーズには適しています。

54
toxalot

この変数はすべてのバージョンのサーバーで使用できるわけではないため、信頼できるテストのみではありません。代わりに、PHPコードを変更して、さらに2つのサーバー環境変数をテストできます。これは、以下のようにhttpsが使用されていることを示すこともできます。

if ( (! empty($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https') ||
     (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
     (! empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443') ) {
    $server_request_scheme = 'https';
} else {
    $server_request_scheme = 'http';
}

Toxalotで述べたように、REQUEST_SCHEMEはバージョン2.4以降のApache Webサーバーのネイティブ変数です。 Apache 2.2にはありません( Apache 2.2サーバー変数) があり、Microsoft IIs 8.5にもありません( IIS 8.5サーバー変数) があります。当然、サーバーによって変数が設定されていない場合、PHPはその変数をグローバル配列$ _SERVERに含めません。

幸いなことに、REQUEST_SCHEMEチェックのみに基づいたコードとの互換性のために、Apache 2.2編集でこの変数を作成できますallホスト設定ファイル(httpd.conf、ssl .conf、000-default.conf、vhosts.conf)、次の行を追加します。

# FOR HOSTS LISTENING AT PORT 80
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=http

# FOR HOSTS LISTENING AT PORT 443
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=https

上記のコードは、すべてのプロトコルに1つの仮想ホストを使用することを前提としています(Apacheのベストプラクティス- this および that を参照)。

11
aldemarcalazans

私もREQUEST_SCHEMEへの参照を見つけることができませんでしたが、リクエストがhttp:またはhttps:によって行われたかどうかを確認したい場合は、$_SERVER['HTTPS']を使用できます。 https:によって。 PHPサイト ここ に文書化されています

7
user1864610

新しいバージョンのNginxでは、デフォルトでfastcgi_param REQUEST_SCHEME $scheme

5
S.A.N

この値はWebサーバーによって異なります。 nginx(v1.10)を使用する場合、ファイル/etc/nginx/fastcgi_params次の行が表示されます。

fastcgi_param  REQUEST_SCHEME     $scheme; 
fastcgi_param  HTTPS              $https if_not_empty;

通常、このデフォルト値で十分です。しかし、動作しない可能性があります。vhostでこの値を強制することができます。

include fastcgi_params;
fastcgi_param  REQUEST_SCHEME     https; 
fastcgi_param  HTTPS              On;

Apacheを使用している場合は、toxalotの答えをご覧ください

3
Arno

CloudFlareユーザーに対するtoxalotの提案の強化:

RewriteEngine on

RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
RewriteRule .* - [E=REQUEST_SCHEME:http]

RewriteCond %{HTTPS} on [OR]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"https"'
RewriteRule .* - [E=REQUEST_SCHEME:https]
2
Sinus Mackowaty

WordPress=が$ -SERVER変数を使用する is_ssl() 関数でこの問題を解決する方法を見るのは興味深い

function is_ssl() {
    if ( isset( $_SERVER['HTTPS'] ) ) {
        if ( 'on' == strtolower( $_SERVER['HTTPS'] ) ) {
            return true;
        }

        if ( '1' == $_SERVER['HTTPS'] ) {
            return true;
        }
    } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
        return true;
    }
    return false;
}
1
Aurovrata

私はこれを使用していますが、現在のスキームを取得する最良の方法だと思います

        $protocol = stripos($_SERVER['SERVER_PROTOCOL'], 'https') === false ? 'http' : 'https';
1
Mr.Hosseini