web-dev-qa-db-ja.com

$ _SERVER ['HTTPS']なしでHTTPSを使用しているかどうかを確認する方法

サーバーがHTTPSで保護されている場合は、$_SERVER['HTTPS']を確認する必要があるという多くのチュートリアルをオンラインで見ました。私の問題は、私が使用する一部のサーバーでは、$_SERVER['HTTPS']が未定義の変数であり、エラーが発生することです。常に定義する必要があるチェック可能な別の変数はありますか?

明確にするために、現在このコードを使用して、HTTPS接続であるかどうかを解決しています。

if(isset($_SERVER['HTTPS'])) {
    if ($_SERVER['HTTPS'] == "on") {
        $secure_connection = true;
    }
}
182
Tyler Carter

これは、$_SERVER['HTTPS']が未定義の場合でも常に機能するはずです。

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

コードはIISと互換性があります。

PHP.netのドキュメントとユーザーのコメント から:

1)スクリプトがHTTPSプロトコルを介して照会された場合、空でない値に設定します。

2)IISでISAPIを使用する場合、HTTPSプロトコルを介して要求が行われなかった場合、値は「オフ」になることに注意してください。 (Fast-CGIアプリケーションとしてPHPを実行しているIIS7でも同じ動作が報告されています)。

また、Apache 1.xサーバー(および壊れたインストール)には、安全に接続しても$_SERVER['HTTPS']が定義されていない場合があります。保証されていませんが、ポート443の接続は convention によって、おそらく secure sockets を使用するため、追加のポートチェックが行われます。

262
Gras Double

私の解決策(標準条件[$ _SERVER ['HTTPS'] == 'on']はロードバランサーの背後のサーバーでは機能しないため):

$isSecure = false;
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
    $isSecure = true;
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
    $isSecure = true;
}
$REQUEST_PROTOCOL = $isSecure ? 'https' : 'http';

HTTP_X_FORWARDED_PROTO:リバースプロキシ(ロードバランサー)はHTTPを使用してWebサーバーと通信する可能性があるため、HTTP要求の発信元プロトコルを識別するためのde facto標準リバースプロキシへのリクエストがHTTPSであっても http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Common_non-standard_request_headers

107
temuraru

Chacha、PHPのドキュメント:「スクリプトがHTTPSプロトコルを介してクエリされた場合、空でない値に設定します。」したがって、HTTPSが実際にオンになっている多くの場合、ifステートメントはfalseを返します。 $_SERVER['HTTPS']が存在し、空でないことを確認する必要があります。特定のサーバーに対してHTTPSが正しく設定されていない場合は、$_SERVER['SERVER_PORT'] == 443かどうかを確認できます。

ただし、一部のサーバーでは$_SERVER['HTTPS']も空でない値に設定されるため、この変数も必ず確認してください。

リファレンス: $_SERVERおよび$HTTP_SERVER_VARSのドキュメント[非推奨]

81
hobodave

これは$_SERVER['HTTPS']が未定義の場合にも機能します

if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 ){
    //enable secure connection
}
13
Thamaraiselvam

Apache mod_sslを使用してサーバーを実行しているときに問題が発生しましたが、phpinfo()とvar_dump($ _SERVER)は、PHPがまだポート80にいると考えていることを示しました。

同じ問題を抱えている人のための私の回避策があります。

<VirtualHost *:443>
  SetEnv HTTPS on
  DocumentRoot /var/www/vhost/scratch/content
  ServerName scratch.example.com
</VirtualHost>

注目に値する行はSetEnv行です。これを設定して再起動すると、常に夢見ていたHTTPS環境変数が必要になります。

9
thomas-peter

あなたがApacheを使用している場合は、常に頼りになるかもしれません

$_SERVER["REQUEST_SCHEME"]

要求されたURLのスキームを確認します。ただし、他の回答で述べたように、SSLが実際に使用されていると想定する前に、他のパラメーターを確認することをお勧めします。

7
Ed de Almeida

以前のすべての投稿を読んで自分の機能を作成する:

public static function isHttps()
{
    if (array_key_exists("HTTPS", $_SERVER) && 'on' === $_SERVER["HTTPS"]) {
        return true;
    }
    if (array_key_exists("SERVER_PORT", $_SERVER) && 443 === (int)$_SERVER["SERVER_PORT"]) {
        return true;
    }
    if (array_key_exists("HTTP_X_FORWARDED_SSL", $_SERVER) && 'on' === $_SERVER["HTTP_X_FORWARDED_SSL"]) {
        return true;
    }
    if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER) && 'https' === $_SERVER["HTTP_X_FORWARDED_PROTO"]) {
        return true;
    }
    return false;
}
6
ling

本当の答え:[config]スクリプトにコピーアンドペーストする準備ができました

/* configuration settings; X=edit may 10th '11 */
$pv_sslport=443; /* for it might be different, as also Gabriel Sosa stated */
$pv_serverport=80; /* X */
$pv_servername="mysite.com"; /* X */

/* X appended after correction by Michael Kopinsky */
if(!isset($_SERVER["SERVER_NAME"]) || !$_SERVER["SERVER_NAME"]) {
    if(!isset($_ENV["SERVER_NAME"])) {
        getenv("SERVER_NAME");
        // Set to env server_name
        $_SERVER["SERVER_NAME"]=$_ENV["SERVER_NAME"];
    }
}
if(!$_SERVER["SERVER_NAME"]) (
    /* X server name still empty? ... you might set $_SERVER["SERVER_NAME"]=$pv_servername; */
}

if(!isset($_SERVER["SERVER_PORT"]) || !$_SERVER["SERVER_PORT"]) {
    if(!isset($_ENV["SERVER_PORT"])) {
        getenv("SERVER_PORT");
        $_SERVER["SERVER_PORT"]=$_ENV["SERVER_PORT"];
    }
}
if(!$_SERVER["SERVER_PORT"]) (
    /* X server port still empty? ... you might set $_SERVER["SERVER_PORT"]=$pv_serverport; */
}

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

$pv_URIprotocolが正しくなり、使用できるようになりました。例$site=$pv_URIprotocol.$_SERVER["SERVER_NAME"]。当然、文字列はTRUEとFALSEで置き換えることもできます。 PVはPortalPress Variableの略で、常に機能するダイレクトコピーペーストです。この作品は、制作スクリプトで使用できます。

これらのパラメーターも許容範囲内であり、Webサーバーを切り替えるときに誤検知がない可能性が高いと思います。

  1. $ _SERVER ['HTTPS_KEYSIZE']
  2. $ _SERVER ['HTTPS_SECRETKEYSIZE']
  3. $ _SERVER ['HTTPS_SERVER_ISSUER']
  4. $ _SERVER ['HTTPS_SERVER_SUBJECT']

    if($_SERVER['HTTPS_KEYSIZE'] != NULL){/*do foobar*/}
    
3
Werezywolf

唯一の信頼できる方法は、Igor Mによって記述されたものです。

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

以下を考慮してください:fastcgiでnginxを使用している場合、デフォルトで(debian、ubuntu)fastgi_paramsはディレクティブを含みます:

fastcgi_param HTTPS $ https;

sSLを使用していない場合、0ではなく「off」ではなく空の値として変換され、運命にあります。

http://unpec.blogspot.cz/2013/01/nette-nginx-php-fpm-redirect.html

3
Galvani

ポートを追加するのは良い考えだとは思いません-特に、ビルドの異なるサーバーがたくさんある場合。変更することを忘れないでください。ドキュメントを見て、カイザーの最後の行はかなり良いと思うので、

if(!empty($_SERVER["HTTPS"]))
  if($_SERVER["HTTPS"]!=="off")
    return 1; //https
  else
    return 0; //http
else
  return 0; //http

完全に十分なようです。

3
sp3c1

SSLは通常ポート443で実行されるため、$_SERVER['SERVER_PORT']を確認できますが、これは絶対確実ではありません。

2
pix0r

これについてどう思いますか?

if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
    $scheme = 'https';
else
    $scheme = 'http';
2
toni rmc

私のサーバー(Ubuntu 14.10、Apache 2.4、php 5.5)では、phpスクリプトがhttps経由でロードされるときに変数$_SERVER['HTTPS']が設定されていません。何が悪いのか分かりません。ただし、.htaccessファイルの次の行はこの問題を修正します。

RewriteEngine on

RewriteCond %{HTTPS} =on [NC] 
RewriteRule .* - [E=HTTPS:on,NE]
2
Karry

私が使用している最短の方法:

$secure_connection = !empty($_SERVER['HTTPS']);

Httpsが使用されている場合、$ secure_connectionはtrueです。

2
Markus Zeller

興味があるだけで、chromeカナリアが送信する瞬間

HTTPS : 1

サーバーに接続します。サーバーの構成方法によっては、次の結果が返されることもあります。

HTTPS : 1, on

オンになっているかどうかをテストしていたため、アプリケーションが壊れましたが、明らかにそうではありません。現時点では、chromeカナリアだけがこれを行うように見えますが、カナリアからのものは一般にしばらくして「通常の」chromeに着陸することに注意する価値があります。

1
John Smith

ここに私がしばらく使用していた再利用可能な関数があります。 HTH。

注:HTTPS_PORT(私のコードではカスタム定数)の値は、環境によって異なる場合があります。たとえば、443または81です。

/**
 * Determine if this is a secure HTTPS connection
 * 
 * @return  bool    True if it is a secure HTTPS connection, otherwise false.
 */
function isSSL()
{
    if (isset($_SERVER['HTTPS'])) {
        if ($_SERVER['HTTPS'] == 1) {
            return true;
        } elseif ($_SERVER['HTTPS'] == 'on') {
            return true;
        }
    } elseif ($_SERVER['SERVER_PORT'] == HTTPS_PORT) {
        return true;
    }

    return false;
}
1
crmpicco
$secure_connection = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || (!empty($_SERVER['HTTP_HTTPS']) && $_SERVER['HTTP_HTTPS'] != 'off') || $_SERVER['REQUEST_SCHEME'] == 'https' || $_SERVER['SERVER_PORT'] == 443) ? true : false;

コードは可能な限りチェックしており、IIS Webサーバーでも機能します。 Chrome v44はヘッダーHTTPを設定しないため:1 HTTP_HTTPSのチェックは問題ありません。このコードがhttpsと一致しない場合、Webサーバーまたはプロキシサーバーの構成が不十分であることを意味します。 Apache自体はHTTPSフラグを正しく設定しますが、プロキシ(nginxなど)を使用すると問題が発生する可能性があります。 nginx https仮想ホストにヘッダーを設定する必要があります

proxy_set_header   X-HTTPS 1;

プロキシからX-HTTPSを探すことにより、いくつかのApacheモジュールを使用してHTTPSフラグを正しく設定します。 mod_fakessl、mod_rpafなどを検索します。

1
mikep

負荷分散システムチェックとしてnginxを使用している場合、$ _ SERVER ['HTTP_HTTPS'] == 1でsslのその他のチェックは失敗します。

1
basis

さらに一歩進んで、接続先のサイトがSSL対応かどうかを判断する機会があります(1つのプロジェクトがユーザーにURLを要求し、APIパックがhttpまたはhttpsサイトにインストールされていることを確認する必要があります)。

私が使用する関数は次のとおりです。基本的に、cURLを介してURLを呼び出して、httpsが機能するかどうかを確認してください。

function hasSSL($url) 
{
    // take the URL down to the domain name
    $domain = parse_url($url, PHP_URL_Host);
    $ch = curl_init('https://' . $domain);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); //its a  HEAD
    curl_setopt($ch, CURLOPT_NOBODY, true);          // no body
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // in case of redirects
    curl_setopt($ch, CURLOPT_VERBOSE, 0); //turn on if debugging
    curl_setopt($ch, CURLOPT_HEADER, 1);     //head only wanted
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);    // we dont want to wait forever
    curl_exec($ch);
    $header = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($header === 200) {
        return true;
    }
    return false;
}

これは、httpsを使用している場合(質問に答える場合)だけでなく、HTTPSを使用している場合(または、SHOULDを使用している場合)を見つけるための最も信頼できる方法です。

注:(実際にはそうではありませんが...)サイトに異なるhttpページとhttpsページが存在する可能性があります(そのため、httpを使用するように指示された場合、変更する必要はありません。)同じであり、おそらくあなた自身を再ルーティングする必要がありますが、この追加のチェックはその用途があります(ユーザーがサイト情報を入力し、サーバー側から確認したいプロジェクトで確かに言ったように)

0
CFP Support

ここで主な提案を使用し、HTTPSが設定されていない場合、ログの「PHP Notice」に悩まされました。 null-coalescing operator "??"を使用して回避できます:

if( ($_SERVER['HTTPS'] ?? 'off') == 'off' ) {
    // redirect
}

(注:php v7より前では使用できません)

0
garafajon

これは私がこれを解決する方法です

$https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 ||
        !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
            strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0;

return ($https) ? 'https://' : 'http://';
0

チェックするすべてのものが正しいことを確認するために、グローバルフィルターを追加します。

function isSSL() {

    $https = filter_input(INPUT_SERVER, 'HTTPS');
    $port = filter_input(INPUT_SERVER, 'SERVER_PORT');
    if ($https) {

        if ($https == 1) {
            return true;
        } elseif ($https == 'on') {
            return true;
        }
    } elseif ($port == '443') {
        return true;
    }

    return false;
}
0
Rodrigo Manara

Incapsulaのロードバランサーを使用している場合は、IRuleを使用してサーバーのカスタムヘッダーを生成する必要があります。ポートが80に設定されている場合は「http」、443に設定されている場合は「https」に等しいHTTP_X_FORWARDED_PROTOヘッダーを作成しました。

0
Nadav