サーバーがHTTPSで保護されている場合は、$_SERVER['HTTPS']
を確認する必要があるという多くのチュートリアルをオンラインで見ました。私の問題は、私が使用する一部のサーバーでは、$_SERVER['HTTPS']
が未定義の変数であり、エラーが発生することです。常に定義する必要があるチェック可能な別の変数はありますか?
明確にするために、現在このコードを使用して、HTTPS接続であるかどうかを解決しています。
if(isset($_SERVER['HTTPS'])) {
if ($_SERVER['HTTPS'] == "on") {
$secure_connection = true;
}
}
これは、$_SERVER['HTTPS']
が未定義の場合でも常に機能するはずです。
function isSecure() {
return
(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| $_SERVER['SERVER_PORT'] == 443;
}
コードはIISと互換性があります。
1)スクリプトがHTTPSプロトコルを介して照会された場合、空でない値に設定します。
2)IISでISAPIを使用する場合、HTTPSプロトコルを介して要求が行われなかった場合、値は「オフ」になることに注意してください。 (Fast-CGIアプリケーションとしてPHPを実行しているIIS7でも同じ動作が報告されています)。
また、Apache 1.xサーバー(および壊れたインストール)には、安全に接続しても$_SERVER['HTTPS']
が定義されていない場合があります。保証されていませんが、ポート443の接続は convention によって、おそらく secure sockets を使用するため、追加のポートチェックが行われます。
私の解決策(標準条件[$ _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
Chacha、PHPのドキュメント:「スクリプトがHTTPSプロトコルを介してクエリされた場合、空でない値に設定します。」したがって、HTTPSが実際にオンになっている多くの場合、ifステートメントはfalseを返します。 $_SERVER['HTTPS']
が存在し、空でないことを確認する必要があります。特定のサーバーに対してHTTPSが正しく設定されていない場合は、$_SERVER['SERVER_PORT'] == 443
かどうかを確認できます。
ただし、一部のサーバーでは$_SERVER['HTTPS']
も空でない値に設定されるため、この変数も必ず確認してください。
これは$_SERVER['HTTPS']
が未定義の場合にも機能します
if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 ){
//enable secure connection
}
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環境変数が必要になります。
あなたがApacheを使用している場合は、常に頼りになるかもしれません
$_SERVER["REQUEST_SCHEME"]
要求されたURLのスキームを確認します。ただし、他の回答で述べたように、SSLが実際に使用されていると想定する前に、他のパラメーターを確認することをお勧めします。
以前のすべての投稿を読んで自分の機能を作成する:
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;
}
本当の答え:[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サーバーを切り替えるときに誤検知がない可能性が高いと思います。
$ _SERVER ['HTTPS_SERVER_SUBJECT']
if($_SERVER['HTTPS_KEYSIZE'] != NULL){/*do foobar*/}
唯一の信頼できる方法は、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
ポートを追加するのは良い考えだとは思いません-特に、ビルドの異なるサーバーがたくさんある場合。変更することを忘れないでください。ドキュメントを見て、カイザーの最後の行はかなり良いと思うので、
if(!empty($_SERVER["HTTPS"]))
if($_SERVER["HTTPS"]!=="off")
return 1; //https
else
return 0; //http
else
return 0; //http
完全に十分なようです。
SSLは通常ポート443で実行されるため、$_SERVER['SERVER_PORT']
を確認できますが、これは絶対確実ではありません。
これについてどう思いますか?
if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
$scheme = 'https';
else
$scheme = 'http';
私のサーバー(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]
私が使用している最短の方法:
$secure_connection = !empty($_SERVER['HTTPS']);
Httpsが使用されている場合、$ secure_connectionはtrueです。
興味があるだけで、chromeカナリアが送信する瞬間
HTTPS : 1
サーバーに接続します。サーバーの構成方法によっては、次の結果が返されることもあります。
HTTPS : 1, on
オンになっているかどうかをテストしていたため、アプリケーションが壊れましたが、明らかにそうではありません。現時点では、chromeカナリアだけがこれを行うように見えますが、カナリアからのものは一般にしばらくして「通常の」chromeに着陸することに注意する価値があります。
ここに私がしばらく使用していた再利用可能な関数があります。 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;
}
$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などを検索します。
負荷分散システムチェックとしてnginxを使用している場合、$ _ SERVER ['HTTP_HTTPS'] == 1でsslのその他のチェックは失敗します。
さらに一歩進んで、接続先のサイトが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を使用するように指示された場合、変更する必要はありません。)同じであり、おそらくあなた自身を再ルーティングする必要がありますが、この追加のチェックはその用途があります(ユーザーがサイト情報を入力し、サーバー側から確認したいプロジェクトで確かに言ったように)
ここで主な提案を使用し、HTTPSが設定されていない場合、ログの「PHP Notice」に悩まされました。 null-coalescing operator "??"を使用して回避できます:
if( ($_SERVER['HTTPS'] ?? 'off') == 'off' ) {
// redirect
}
(注:php v7より前では使用できません)
これは私がこれを解決する方法です
$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://';
チェックするすべてのものが正しいことを確認するために、グローバルフィルターを追加します。
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;
}
Incapsulaのロードバランサーを使用している場合は、IRuleを使用してサーバーのカスタムヘッダーを生成する必要があります。ポートが80に設定されている場合は「http」、443に設定されている場合は「https」に等しいHTTP_X_FORWARDED_PROTOヘッダーを作成しました。