コンピューター ウィンドウズ インターネット

PHPのHTTP_HOSTとSERVER_NAMEの違いは何ですか? PHP $ _SERVERグローバル配列環境変数HTTP_X_FORWARDED_FORを取得しています

$ _SERVER PHPで最も重要な定義済み配列の1つです。 これには、PHPインタープリターがサーバーから受け取った変数が含まれています。 誰もがこれらの変数を使用しました。そうしないと、Webアプリケーションの完全なサポートを整理するのがかなり難しいため、間違いなく使用します。

私の記事では、$ _ SERVERスーパーグローバル配列の主な変数を含むテーブルを提案します。 このテーブルは、PHP文字列関数用に作成されたものと似ています。

$ _SERVER配列のすべての要素を表示するには、次のことを行う必要があります。a)配列を出力するprint_r()関数を呼び出す。 b)phpinfo()関数を呼び出すか、PHPインタープリターに関する情報を表示します。

$ HTTP_SERVER_VARSについて簡単に説明します

$ _SERVERスーパーグローバル配列は、PHP4.1.0の$ HTTP_SERVER_VARS配列を置き換えます。 $ HTTP_SERVER_VARS現在は使用されていませんが、知っておく価値があります。 まず第一に、古いバージョンはオートグローバルではありませんでした。 2番目の違いは、$ _SERVER配列の一部の要素が$ HTTP_SERVER_VARSに存在しないことですが、ほとんどの場合、それらの変数は同じです。

エレメント

簡単な説明

$ _SERVER ["DOCUMENT_ROOT"]

サーバーのルートディレクトリへのパスが含まれます。

$ _SERVER ["HTTP_HOST"]

$ _SERVER ["SERVER_NAME"]

$ _SERVER ["SCRIPT_FILENAME"]

仮想ホストのルートディレクトリから始まる、スクリプトの名前が含まれます。

C:\フォルダー\ index.php

/www/folder/index.php

$ _SERVER ["PHP_SELF"]

$ _SERVER ["SCRIPT_NAME"]

スクリプトの名前が含まれています。

$ _SERVER ["REQUEST_URI"]

会社のホストのルートディレクトリから始まるスクリプトの名前と、GETメソッドによってスクリプトに渡されたパラメータが含まれます。

/www/folder/index.php?page=2&num=5

$ _SERVER ["QUERY_STRING"]

GETメソッドによってスクリプトに渡されるパラメーターが含まれます。

住所について

http://site.com/index.php?page=2&num=5

出力されます

$ _SERVER ["REQUEST_METHOD"]

スクリプトを呼び出すために使用されるrequestメソッドが含まれています。

得る また役職

$ _SERVER ["HTTP_REFERER"]

訪問者がアクセスしたページのアドレスが含まれます。

http://yandex.ru/yandsearch

$ _SERVER ["HTTP_USER_AGENT"]

訪問者のブラウザとオペレーティングシステムのタイプとバージョンが含まれています。 また、検索ロボットや携帯電話のブランドを検出することもできます。 以下は、電話のブランドと文字列内の暗号の比較です。

ノキア-NOKIA; SonyEricsson-ERICSSONまたはSONYERICSSON; サムスン-SAMSUNGまたはSEC-; モトローラ-MOT; LG-LGまたはLG-; Alcatel-ALCATEL; パナソニック-PANASONIC; Sagem-SAGEM; Pantech-PANTECH; シーメンス-SIE; BenQ-BENQ; NEC-NEC; シャープ-シャープ。

Mozilla / 4.0(互換性; MSIE 6.0; Windows NT 5.1)( IE 6Windows XP)

Mozilla / 4.0(互換性; MSIE 7.0; Windows NT 5.0)Opera 9.50( Opera 9.5Windows 2000)

$ _SERVER ["REMOTE_ADDR"]

クライアントのIPアドレスが含まれます。

$ _SERVER ["SERVER_ADDR"]

サーバーのIPアドレスが含まれます。

$ _SERVER ["HTTP_ACCEPT"]

ドキュメントタイプに対するクライアントの設定について説明します。 この要素のコンテンツは、クライアントによってサーバーに渡されるAcceptHTTPヘッダーから取得されます。

出力形式:MIMEタイプ[[; q]、別のMIMEタイプ[; NS] ...]

いくつかの優先MIMEタイプが存在する可能性があり、それらはコンマで区切られます。 *は、テンプレート、グループ化を設定するために使用されます。 q-選好係数(デフォルトでは1)は、0から1の範囲です。

image / jpeg、image / x-xbitmap、application / x-shockwave-flash

画像 / *; q = 0.5、画像/ jpeg (他のすべての形式よりもzhpegを優先します)

$ _SERVER ["HTTP_ACCEPT_LANGUAGE"]

前の要素と似ていますが、言語設定に関連しています。 訪問者の国籍を判断するために使用できます。 ただし、英語版のブラウザを使用することを好む人もいるため、見積もりは概算になります。

ru、en; q = 0.9 (ロシア語を好みますが、ロシア語がない場合は英語でかまいません)

$ _SERVER ["HTTP_ACCEPT_CHARSET"]

前のものと同様です。 Accept-Charsetヘッダーが含まれています

$ _SERVER ["HTTP_ACCEPT_ENCODING"]

前のものと同様です。 Accept-Encodingヘッダーが含まれています

$ _SERVER ["SERVER_PORT"]

サーバーリスニングポートが含まれます。

$ _SERVER ["SERVER_SOFTWARE"]

Webサーバーに関する情報が含まれています。

Apache / 2.2.4(Win32)

$ _SERVER ["SERVER_PROTOCOL"]

HTTPプロトコルのバージョンが含まれています。

$ _SERVER ["GATEWAY_INTERFACE"]

Webサーバーで使用されるCGIのバージョンが含まれます。

$ _SERVER ["REQUEST_TIME"]

UNIX形式のWebページ要求の開始時刻。 PHP5.1.0以降で利用可能

パラメータを含むページの完全なアドレス:

echo "http://" .SERVER_NAME。$ _ SERVER ["REQUEST_URI"];
?>

すべての機能を含む表は、リンクから* .doc形式でダウンロードできます。

$ _SERVER ["REQUEST_URI"]変数に特に注意し、それをチェックすることを忘れないでください!重要なのは、その使用は特に安全ではないかもしれないということです。 たとえば、サイトでは、このパラメーターを使用していくつかのURLが生成されます。 次に、ブラウザの行にリンクhttp://site.com/index.phpを書き込むことができますか?”>..。 これにより、Cookieファイルの内容を示すウィンドウが表示されます。 この例は無害ですが、ハッカーが違反を悪用して、たとえば別のユーザーからデータを盗むことができる穴です。 したがって、変数に無効な文字がないか確認してください。特に>と<.

今日は、おそらくすべて。 次回と幸せな週末まで!

JavaScriptはブラウザでブロックされています。 サイトが機能するようにJavaScriptを有効にしてください!

スーパーグローバルアレイ$ _SERVER

配列に $ _SERVER PHPインタープリターは、サーバーから受け取った変数を入力します。 これらの変数がないと、Webアプリケーションを完全にサポートすることは困難です。 以下は、スーパーグローバルアレイの最も重要な要素の説明です。 $ _SERVER.

コメント

  • $ _SERVER配列要素の完全なリストを表示する
  • 配列のダンプを出力するprint_r()関数を使用するか、PHPインタープリターに関する情報を表示するphpinfo()関数を使用できます。

    配列(=> on => 200 => on => htmlweb.ru => https => 443 => close => Mozilla / 5.0(互換; Googlebot / 2.1; + http://www.google.com/bot。 html)=> * / * => beget = begetok; => gzip、deflate => / usr / local / sbin:/ usr / local / bin:/ usr / sbin:/ usr / bin:/ sbin:/ bin = > => Apache / 2.4.25(Debian)mpm-itk / 2.4.7-04 OpenSSL / 1.0.2l => htmlweb.ru => 185.12.92.137 => 80 => 144.76.78.4 => / var / www / htmlweb / data / www / htmlweb.ru => http => => /var/www/htmlweb/data/www/htmlweb.ru => [メール保護]=>。php => 35242 => /php/function/$_server.php => CGI / 1.1 => HTTP / 1.0 => GET => => /php/function/%24_server.php => /index.php => /index.php => 1560059525.711 => 1560059525)1

    $ _SERVER [" DOCUMENT_ROOT"]

    $ _SERVER ["DOCUMENT_ROOT"]要素には、サーバーのルートディレクトリへのパスが含まれます。スクリプトが仮想ホストで実行される場合、この要素は仮想ホストのルートディレクトリへのパスを指定します。 それらの。 httpd.conf構成ファイルでは、仮想ホストに値 "D:/ main"が割り当てられたDocumentRootディレクティブがあり、$ _SERVER ["DOCUMENT_ROOT"]要素には値 "D:main"が含まれます。

    $ _SERVER [" REMOTE_ADDR"]

    $ _SERVER ["REMOTE_ADDR"]要素には、クライアントのIPアドレスが含まれています。 ローカルマシンでテストする場合、このアドレスは127.0.0.1になります。 ただし、ネットワークでテストする場合、変数はクライアントのIPアドレス、またはクライアントがサーバーに到達した最後のプロキシサーバーを返します。 クライアントがプロキシサーバーを使用している場合は、HTTP_X_FORWARDED_FOR環境変数を使用してIPアドレスを確認できます。この変数の値は、getenv()関数を使用して取得できます。

    コメント

    プロキシサーバーは、トラフィックの圧縮、データの暗号化、モバイルデバイスへの適応など、特別なタイプのサービスを提供する特別な中間サーバーです。 多くのプロキシサーバーの中には、クライアントの実際のIPアドレスを非表示にできるいわゆるアノニマイザーサーバーがあります。このようなサーバーは、HTTP_X_FORWARDED_FOR環境変数を返しません。

    環境変数の抽出 HTTP_X_FORWARDED_FOR

    echo @getenv(HTTP_X_FORWARDED_FOR);

    $ _SERVER [" SCRIPT_FILENAME"]

    $ _SERVER ["SCRIPT_FILENAME"]要素には、ディスクのルートからファイルへの絶対パスが含まれています。 したがって、サーバーがWindowsオペレーティングシステムを実行している場合、このパスは「d:mainestindex.php」のようになります。 パスはディスクから指定されます。UNIXライクなオペレーティングシステムでは、パスはルートディレクトリ/から指定されます(例: "/ var / share / www / test / index.php")。

    /var/www/htmlweb/data/www/site/index.php

    $ _SERVER [" サーバーの名前"]

    $ _SERVER ["SERVER_NAME"]要素には、原則として、そこにあるサイトのドメイン名と同じサーバー名が含まれています。 例えば、

    $ _SERVER ["SERVER_NAME"]要素の内容は、多くの場合、$ _SERVER ["HTTP_HOST"]要素の内容と同じです。 $ _SERVERスーパーグローバル配列を使用すると、サーバー名に加えて、サーバーのIPアドレス、リスニングポート、インストールされているWebサーバー、HTTPプロトコルのバージョンなどのサーバーパラメーターの数を確認できます。 この情報は、それぞれ$ _SERVER ["SERVER_ADDR"]、$ _SERVER ["SERVER_PORT"]、$ _SERVER ["SERVER_SOFTWARE"]、および$ _SERVER ["SERVER_PROTOCOL"]に配置されます。 以下は、これらのアイテムを使用した例です。

    $ _SERVER配列の要素を使用する

    echo "サーバー名は"です。$ _ SERVER ["SERVER_NAME"]。 "
    "; echo"サーバーIPは "。$ _ SERVER [" SERVER_ADDR "]。"
    "; echo"サーバーポートは "。$ _ SERVER [" SERVER_PORT "]。"
    "; echo" Webサーバー-"。$ _ SERVER [" SERVER_SOFTWARE "]。"
    "; echo" HTTPプロトコルバージョン-"。$ _ SERVER [" SERVER_PROTOCOL "]。"
    ";

    サーバー名-サイト
    サーバーIP-185.12.92.137
    サーバーポート-80
    Webサーバー-Apache / 2.4.25(Debian)mpm-itk / 2.4.7-04 OpenSSL / 1.0.2l
    HTTPプロトコルバージョン-HTTP / 1.0

    $ _SERVER [" REQUEST_METHOD"]

    $ _SERVER ["REQUEST_METHOD"]要素には、スクリプトの呼び出しに使用されるリクエストメソッド(GETまたはPOST)が含まれています。

    エコー$ _SERVER ["REQUEST_METHOD"];

    $ _SERVER [" クエリ文字列"]

    $ _SERVER ["QUERY_STRING"]要素には、クエリ文字列がアドレスの場合にスクリプトに渡されるパラメータが含まれます

    たとえば、以下を参照する場合:
    $ _SERVER ["QUERY_STRING"]要素には、「?」記号の後のすべてのテキストが含まれます。

    エコー$ _SERVER ["QUERY_STRING"];

    id = 1&test = wet&id_theme = 512

    $ _SERVER [" PHP_SELF"]

    $ _SERVER ["PHP_SELF"]要素には、仮想ホストのルートディレクトリから始まるスクリプトの名前が含まれています。 クエリ文字列がアドレスの場合 http://www.mysite.ru/test/index.php?id=1&test=wet&id_theme=512 その場合、$ _SERVER ["PHP_SELF"]要素にはスニペットが含まれます 「/test/index.php」..。 通常、同じフラグメントが$ _SERVER ["SCRIPT_NAME"]要素に配置されます。

    $ _SERVER [" REQUEST_URI"]

    要素$ _SERVER ["REQUEST_URI"]には、仮想ホストのルートディレクトリとパラメータから始まるスクリプトの名前が含まれています。 クエリ文字列がアドレスの場合: http://www.mysite.ru/test/index.php?id=1&test=wet&id_theme=512 その場合、$ _SERVER ["REQUEST_URI"]要素にはスニペットが含まれます "/test/index.php?id=1&test=wet&id_theme=512"..。 クエリ行に配置されているスクリプト内の完全なアドレスを復元するには、以下に示す$ _SERVER配列の要素の組み合わせを使用するだけで十分です。

    スクリプトへの完全なアドレス

    echo "http://"。$ _ SERVER ["SERVER_NAME"]。$ _ SERVER ["REQUEST_URI"];
    • 翻訳
    • チュートリアル

    php 5.4の最もクールな新機能の1つは、開発とテスト用に特別に構築された組み込みサーバーです。 これで、完全なWebサーバーがなくてもコードを記述してテストできます。組み込みサーバーを起動し、コードをテストして、完了したらシャットダウンするだけです。
    サーバーはまた、創造的な使用の機会を提供します。 たとえば、ポータブルWebアプリケーションをCDまたはUSBで配布したり、GTKやその他のグラフィックライブラリを使用せずにPHPで構築されたデスクトップアプリケーションとして配布したりすることができます。

    PHPマニュアルでは、組み込みサーバーは開発用であり、本番サーバーでは使用しないことをお勧めします。 サーバーを担当するINIディレクティブはありません(コンソールの出力に色を付けることを除いて)。ドキュメントの主なアイデアは、「Webサーバーもあります。そのままにしておきます」ということのようです。
    とにかく、組み込みサーバーは貴重な開発およびテストツールになると思います。 たとえば、私のマシンでは、自分に合ったカスタム構成でプリインストールされたApacheを使用していますが、新しいWebアプリケーションを試してみたい場合があります。 組み込みWebサーバーを使用すると、ダウンロードフォルダーまたは一時フォルダーから直接アプリケーションをテストし、必要な場合にのみ通常の環境に移動できます。
    しかし、初心者にとっては、書かれた多くのアプリケーションが.htaccessとmod_rewriteを使用するため、それほど簡単ではありません。 しかし、誰か(多分あなたの一人、なぜそうではないのですか?)がこれのためのアダプターを書くと確信しています、そして私はそれを最初にテストしたいと思います。
    この記事では、組み込みサーバーの基本的な使用例をいくつか説明し、組み込みサーバーを開発とテストに役立てる方法を示します。

    内蔵サーバーを使用しています

    したがって、サーバーを使用するには、php5.4以降が必要です。 PHPのバージョンを確認するには、次のコマンドを実行します。
    php -v
    次のコマンドを実行して、サーバーがアセンブリで使用可能かどうかを確認することもできます。
    php -h
    サーバーでのみ使用される「-S」および「-t」オプションの説明を探してください。
    サーバーを確認するには、現在のディレクトリにindex.phpファイルを作成します。このファイルには、phpinfo()関数の呼び出しが含まれており、サーバーを起動します。
    $ php -S 127.0.0.1:8080 PHP5.4.0RC7開発サーバーは2012年2月26日金曜日18:49:29に開始されました127.0.0.1:8080をリッスンしていますドキュメントルートは/ home / ec2-userCtrl-Cを押して終了します。
    そして今、あなたは埋め込まれたウェブサーバーによって提供されるコンテンツを見ることができます:

    各クライアント要求はコンソールに書き込まれます。
    80.180.55.37:36318 : / 80.180.55.37:36584 : /
    戻って、サーバーにアクセスできるアドレスを指定するために使用される「-S」コマンドラインパラメーターを見てみましょう。 可能な値:
    ローカルホスト-サーバーにはローカルマシンからのみアクセスできます。
    0.0.0.0 -マシンの任意のインターフェイスで、
    外部IPまたは灰色のIP-指定されたIPのみ
    -tオプションは、指定されたディレクトリルートを設定します。 例えば:
    $ php -S :8090 -t / home / ec2-user / public
    その上、。 特定のルーターファイルの名前を指定できます。 例えば:
    $ php -S> localhostまたはパブリックIP>:8080 -t / home / ec2-user / public public / index.php
    このルーターの出力は、サーバーによって解析および実行されます。 簡単な例:
    PHPへようこそ

    ";
    スクリプトがFALSEを返す場合、要求されたURIはサーバーによって処理され、サーバーは要求されたリソースを発行するか、404エラーを返します。 スクリプトが他のものを返す場合、スクリプトの出力はクライアントに渡されます。
    このアプローチにより、より詳細に制御できますが、知っておくべきことがいくつかあります。 まず、PHPサーバーは最小限のHTTPヘッダーセットのみを送信します。
    接続:クローズコンテンツタイプ:テキスト/ htmlホスト:aws-dev-01.vtardia.com X-Powered-By:PHP / 5.4.0RC7 D
    これをApacheサーバーによって返されるヘッダーと比較してください。
    Accept-Ranges:bytes接続:Keep-Alive Content-Length:631 Content-Type:text / html Date:Sat、04 Feb 2012 18:24:42 GMT Etag: "bbb99-277-4ace8c5470a40" Keep-Alive:timeout = 15、最大= 100最終変更日:2011年9月14日水曜日15:54:09 GMTサーバー:Apache / 2.2.21(Unix)DAV / 2
    アプリケーションでヘッダーを使用する場合は、開発環境と本番環境の違いを考慮する必要があります。
    次に、組み込みサーバーには異なるSAPI(サーバーAPI)があります。 したがって、インデックスphpでルーティングを実行することにより、テストサーバーまたは本番サーバーでスクリプトへの呼び出しを定義できます。 php_sapi_name()は、組み込みサーバーで「cli-server」を返します。
    「cli_server.color」と呼ばれる特別なINIディレクティブが1つあります。 このディレクティブは、色付きの出力をコンソールに返します。 名前の付いた空のファイルを作成します cli-server.ini次の行を挿入します。
    cli_server.color = on
    INIファイルで必要なディレクティブを指定することにより、サーバーに固有の環境構成を作成できます。 宣言されていないディレクティブは、デフォルト値を受け入れます。 これで、ディレクティブを1つだけ宣言しました- cli_server.color.
    INIファイルを指定する「-c」パラメータを使用してサーバーを起動します。
    $ php -S localhost -c cli-server.ini
    端末が色をサポートしている場合は、コンソールに「色付き」の出力が表示されるはずです。 200ステータスは緑色で強調表示され、404ステータスはオレンジ色で強調表示され、スクリプトエラーは赤色で強調表示されます。

    パーソナルサーバーを作成します

    組み込みサーバーについて知っておくべきことがすべてわかったので、何かクールなことをしましょう。 自分だけのポータブルサーバーを作ろう!
    アプリケーションの次の構造から始めます。

    ライブラリフォルダにはアプリケーションコードが含まれ、publicはルートディレクトリであり、index.phpといくつかの静的ファイルが含まれています。 このチュートリアルでは「server」フォルダーに焦点を当てるので、アプリケーションは単純な「HelloWord!」で構成されます。 そしていくつかの写真とCSS。
    私たちの目標は、1つのコマンドでアプリケーションディレクトリからサーバーを起動できるようにすることです。サーバーがルーティング、HTTPヘッダー、エラーを処理します。
    $ ./start.sh
    起動スクリプトを見てみましょう。
    #! / bin / bash INIFILE = "$(pwd)/server/server.ini" DOCROOT = "$(pwd)/ public" ROUTER = "$(pwd)/server/router.php" HOST = 0.0.0.0 PORT = 8080 PHP = $(どのphp)if [$? != 0]; 次に、「PHPが見つかりません」とエコーします。exit1fi $ PHP -S $ HOST:$ PORT -c $ INIFILE -t $ DOCROOT $ ROUTER
    スクリプトはアプリケーションディレクトリから実行されると想定しているため、INIFILE、DOCROOT、ROUTERはpwdを使用して定義されます。 phpへのパスは、whichコマンドを使用して決定されます。 ユーザーの$ PATHにphpが見つからなかった場合、スクリプトはエラーで失敗します。
    これは十分に機能しますが、コマンドラインから指定されたパラメーターのいずれかを変更できるようにユーザーに提供しましょう。次に例を示します。
    もしも [! -z $ INIFILE]; 次に、INIFILE = "$(pwd)/server/server.ini" fi
    続いて、「errors」フォルダにはHTTPエラーメッセージのファイルが含まれています。 403エラーの例を次に示します。HTMLのみを使用しましたが、スクリプトは含まれますが、 含むしたがって、任意のphpコードを使用できます。
    403

    403禁止します

    申し訳ありませんが、リクエストされたリソースにアクセスできません。



    それでは、router.phpを見てみましょう。 このファイルのタスクは、このファイルが存在する場合にのみ、すべての要求を受信して​​管理し、それらをサーバーに転送することです。 テンプレートを接続すると、すべてのエラーページが表示されます。
    最初の行では、エラーテンプレートのあるディレクトリであるDIRECTORY_INDEXなどのグローバルパラメータを定義します。 date_default_timezone_set()パラメーターはOS設定と一致する必要があります。一致しない場合、ログとサーバーのエントリ間に不整合が発生します。 また、セキュリティを向上させるために、許可されるIPアドレスのリストを追加しました。
    logAccess()関数が必要なのは、ルーティングスクリプトが要求を受け入れると、サーバーログがデフォルトで無視されるためです。 この関数はステータスコードのみを受け入れ、出力形式はサーバー形式と完全に一致しています。
    最初のタスクはセキュリティをチェックすることです。 クライアントのIPが許可されたIPの配列にない場合は、エラーメッセージを表示して、スクリプトを終了します。 200以外のステータスコードを指定する必要があり、ヘッダー()関数はここでは機能しないため、新しい関数http_response_codeを使用します。
    クライアントのIPが許可されたIPの配列に含まれている場合、次のステップは、要求されたパスとファイル拡張子を取得することです。 拡張機能が空の場合、ユーザーがフォルダーを要求していると想定し、最初に定義されたDIRECTORY_INDEXを使用してパスを作成します。
    最後に、要求されたファイルが存在する場合は、FALSEを返し、サーバーにファイルへのアクセスを許可します。 そうでない場合は、404エラーメッセージが表示されます。

    概要

    それがすべてです。 ご覧のとおり、phpサーバーは使いやすいです。 私たちのパーソナルサーバーはとてもシンプルです。 コードを最適化して、より複雑で機能的なクラスに組み込むことができます。 ハッピーコーディング!

    p.s. 翻訳に対する批判やコメントは個人的に喜んで受け入れます。

    そして、それはクライアントが実際にリクエストの「ターゲットホスト」として使用したものです。 SERVER_NAMEは、サーバー構成で定義されています。 どちらが必要かによって異なります。 これはクライアント制御の値であるため、ビジネスロジックでの使用には信頼性がなく、もう1つはサーバー制御の値であり、より信頼性が高いことを理解する必要があります。 ただし、WebサーバーのSERVER_NAME構成が正しいことを確認する必要があります。 Apache HTTPDを例にとると、そのドキュメントからの抜粋を次に示します。

    ServerNameが指定されていない場合、サーバーはIPアドレスの逆引き参照を実行してホスト名を推測しようとします。 ServerNameにポートが指定されていない場合、サーバーは着信要求のポートを使用します。 最適な信頼性と予測可能性を得るには、ServerNameディレクティブを使用して明示的なホスト名とポートを指定する必要があります。

    更新:ボビンスの回答へのリンクを含む質問に対するペッカの回答を確認した後、PHPは常にSERVER_NAMEのHTTP_HOST値を返します。これは、数年前の私自身のPHP 4.x + Apache HTTPD1.2.xの経験とは対照的です。 Windows XP(Apache HTTPD 2.2.1 with PHP 5.2.8)で現在のXAMPPのほこりを吹き飛ばし、それを実行し、両方の値を出力するPHPページを作成し、URLConnectionを使用してホストヘッダーを変更するJavaテストアプリケーションを作成しました。そしてテストは、これが確かに(間違った)ケースであることを私に教えてくれました。

    最初にPHPを疑って、いくつかを掘り下げた後 PHPエラーレポートこの件に関して、問題の原因は使用中のWebサーバーにあり、SERVER_NAMEが要求されたときにHTTPホストヘッダーを正しく返さなかったことがわかりました。 だから私は掘り下げました ApacheHTTPDエラーレポートを使用して さまざまなキーワード主題に関して、そして私はついに関連する誤りを見つけました。 この動作は、Apache HTTPD1.3以降で導入されました。 エントリでUseCanonicalNameディレクティブをオンに設定する必要があります httpd.confのServerName(ドキュメントの下部にある警告も確認してください!)。

    ServerName example.com UseCanonicalName on

    これは私のために働いた。

    一般化すると、SERVER_NAMEの方が信頼性が高くなりますが、 依存サーバー構成で!

    HTTP_HOSTは、クライアントによって送信されるターゲットホストです。 ユーザーはユーザーを自由に操作できます。 www.stackoverflow.comの値に対するHTTP_HOSTリクエストを使用してサイトにリクエストを送信する必要はありません。

    SERVER_NAMEはVirtualHostサーバーの定義に由来するため、より信頼性が高いと見なされます。 また、Webサーバーのセットアップに関連する特定の条件下で外部から操作することもできます。 これを見る このSOの質問これは、両方のオプションの安全面を扱います。

    安全であるために頼る必要はありません。 ただし、どちらを使用するかは、実際に何をしたいかによって異なります。 スクリプトが実行されているドメインを特定する場合は、攻撃者からの無効な値が何も壊さない限り、HTTP_HOSTを安全に使用できます。

    IPv6を使用する場合は、SERVER_NAMEではなくHTTP_HOSTを使用することをお勧めします。 http:// [:: 1] /と入力すると、環境変数は次のようになります。

    HTTP_HOST = [:: 1] SERVER_NAME = :: 1

    これは、たとえばmod_rewriteを実行すると、厄介な結果が得られる可能性があることを意味します。 SSLリダイレクトの例:

    #SERVER_NAMEは機能しません-httpsへのリダイレクト:// :: 1 /RewriteRule。*Https://%(SERVER_NAME)/#HTTP_HOSTは機能します-httpsへのリダイレクト:// [:: 1]/RewriteRule。*Https: //%(HTTP_HOST)/

    これは、ホスト名なしでサーバーにアクセスしている場合にのみ適用されます。

    server.phpをチェックしたい場合、または次のように呼び出したい場合:

    次に、サイトのすべての有効なURLにアクセスし、違いを確認します。

    「SERVER_NAMEの信頼性が高い」とはどういう意味か理解するのに少し時間がかかりました。 共有サーバーを使用していますが、仮想ホストディレクティブにアクセスできません。 そのため、.htaccessでmod_rewriteを使用して、さまざまなディレクトリのさまざまなHTTP_HOSTをマップしています。 この場合、このHTTP_HOST値は理にかなっています。

    名前ベースの仮想ホストを使用している場合も状況は似ています。仮想ホスト内のServerNameディレクティブは、どのホスト名がその仮想ホストにマップされるかを示すだけです。 つまり、どちらの場合も、要求中にクライアントから提供されたホスト名(HTTP_HOST)は、サーバー上の名前と一致する必要があります。サーバー自体はディレクトリにマップされます。 マッピングが仮想ホストディレクティブで行われるか、htaccess mod_rewriteルールで行われるかは、ここでは二次的なものです。 このような場合、HTTP_HOSTはSERVER_NAMEと同じになります。 Apacheがこのように構成されていることをうれしく思います。

    ただし、状況はIPベースの仮想ホストとは異なります。 この場合、そしてこの場合にのみ、SERVER_NAMEとHTTP_HOSTは異なる可能性があります。これは、クライアントが名前ではなくIPによってサーバーを選択するためです。 実際、これが重要な特別な構成が存在する場合があります。

    したがって、これからは、コードがこれらの特別な構成にプッシュされる場合に備えて、SERVER_NAMEを使用します。

    簡単なセットアップ(CentOS 7、Apache 2.4.x、PHP 5.6.20)と1つのWebサイト(共有ホスティングなし)があると仮定します...

    PHPの意味では、$ _SERVER ["SERVER_NAME"]は、httpd.confのApache構成(** ServerName **ディレクティブとUseCanonicalNameOn)に基づいて$ _SERVERスーパークラスに登録されたPHP要素です(有効な仮想ホスト構成からかどうかは関係ありません)。ファイル、何でもなど)。 HTTP_HOST HTTPホストヘッダーから推測されます。 ユーザー入力のように扱います。 使用前にろ過して確認してください。

    これは、比較の基礎として$ _SERVER ["SERVER_NAME"]を使用している例です。 次のメソッドは、ServerValidator(Validatorの子)という名前の特定の子クラス用です。 ServerValidatorは、使用する前に$ _SERVER内の6つまたは7つのアイテムを検証します。

    HTTPリクエストがPOSTであるかどうかを判断するときは、この方法を使用します。

    パブリック関数isPOST()(return(($ this-> requestMethod === "POST")&& //無視$ this-> hasTokenTimeLeft()&& //無視$ this-> hasSameGETandPOSTIdentities()&& // Ingore($ this -> httpHost === filter_input(INPUT_SERVER、 "SERVER_NAME")));)

    このメソッドが呼び出されるまでに、対応する$ _SERVER要素(および対応するプロパティセット)のすべてのフィルタリングと検証が行われます。

    ($ this-> httpHost === filter_input(INPUT_SERVER、 "SERVER_NAME")

    $ _SERVER ["HTTP_HOST"](最終的には要求されたHTTPホストヘッダーから派生)の値が$ _SERVER ["SERVER_NAME"]と一致することを確認します。

    現在、スーパーグローバルカンバセーションを使用して例を説明していますが、これは、filter_input_array()に関連するINPUT_GET、INPUT_POST、およびINPUT_SERVERに慣れていない人がいるためです。

    肝心なのは、4つの条件がすべて満たされない限り、サーバーでPOST要求を処理しないということです。 したがって、POST要求に関しては、厳密なブラウザーにHTTPホストヘッダー(以前に存在が確認された)の運命の呪文を提供することを拒否します。 HTTP 1.0..。 さらに、要求されたホストは値と一致する必要があります サーバーの名前 httpd.confにあり、拡張機能として、$ _ SERVERスーパーマクルの$ _SERVER( "SERVER_NAME")の値。 繰り返しになりますが、PHPフィルター関数でINPUT_SERVERを使用しますが、あなたは私のドリフトを壊していました。

    balusCが指摘しているように、SERVER_NAMEは信頼性が低く、ユーザーとサーバーの間にある可能性のあるApache構成、サーバー構成、およびファイアウォールで変更される可能性があります。

    次の関数は、常にポートのない実際のホスト(ユーザーが入力したホスト)を返します。これはほぼ信頼性があります。

    関数getRealHost()(list($ realHost、)= explode( ":"、$ _ SERVER ["HTTP_HOST"]); return $ realHost;)

    共有する

    まず、アバターをアップロードする機能を追加して、登録ページを改善します。 元の画像はjpg、gif、またはpng形式である必要があります。 また、2MBを超えないようにする必要があります。 スクリプトで圧縮すると、アバターのサイズは約3 kb、jpg形式になりますのでご安心ください。 ページを開く reg。phpタグを追加します < > ライン enctype = "multipart / form-data"例のように:


    登録










    今、私たちは保存します reg.php

    2.次に、テーブルに別のフィールドを作成する必要があります ユーザー..。 に移動 phpmyadmin、必要なベースとテーブルを選択します。


    写真のように、すべての値を設定します。

    アバターへのパスはこのフィールドに書き込まれ、別のフォルダーに保存されます。これを「アバター」と呼びましょう。 フォルダは、残りのスクリプトファイルと同じディレクトリに配置されます。

    3.ファイルに移動します 保存する_ ユーザー. phpログインとパスワードからスペースを削除した後、次のコードを追加します。

    //余分なスペースを削除します
    $ login = trim($ login);

    //新しいものを追加します*******************************************

    //ログインとパスワードの長さのチェックを追加します
    if(strlen($ login)< 3 or strlen($login) > 15) {
    exit( "ログインは3文字以上15文字以下である必要があります。");
    }
    if(strlen($ password)< 3 or strlen($password) > 15) {
    exit( "パスワードは3文字以上15文字以下である必要があります。");
    }

    if(!empty($ _ POST ["fupload"]))//ユーザーが画像を投稿したかどうかを確認します
    {
    $ fupload = $ _ POST ["fupload"]; $ fupload =トリム($ fupload);
    if($ fupload == ""またはempty($ fupload))(
    unset($ fupload); // $ fupload変数が空の場合は、削除します
    }
    }
    if(!isset($ fupload)またはempty($ fupload)または$ fupload == "")
    {
    //変数が存在しない場合(ユーザーが画像を送信しなかった場合)、「アバターなし」という碑文が付いた事前に準備された画像を割り当てます
    $ avatar = "avatars / net-avatara.jpg"; // net-avatara.jpgを描画するか、ソースを取り込むことができます
    }
    そうしないと
    {
    //それ以外の場合-ユーザー画像をロードします
    $ path_to_90_directory = "avatars /"; //初期画像とその圧縮コピーが読み込まれるフォルダー

    If(preg_match( "/ [。](JPG)|(jpg)|(gif)|(GIF)|(png)|(PNG)$ /"、$ _ FILES ["fupload"] ["name"]) )//元の画像の形式を確認します
    {
    $ filename = $ _FILES ["fupload"] ["name"];
    $ source = $ _FILES ["fupload"] ["tmp_name"];
    $ target = $ path_to_90_directory。 $ファイル名;
    move_uploaded_file($ source、$ target); //オリジナルを$ path_to_90_directoryフォルダーにアップロードします
    if(preg_match( "/ [。](GIF)|(gif)$ /"、$ファイル名))(
    $ im = imagecreatefromgif($ path_to_90_directory。$ filename); //オリジナルがgif形式の場合は、同じ形式で画像を作成します。 その後の圧縮に必要
    }
    if(preg_match( "/ [。](PNG)|(png)$ /"、$ファイル名))(
    $ im = imagecreatefrompng($ path_to_90_directory。$ filename); //オリジナルがpng形式の場合は、同じ形式で画像を作成します。 その後の圧縮に必要
    }

    If(preg_match( "/ [。](JPG)|(jpg)|(jpeg)|(JPEG)$ /"、$ filename))(
    $ im = imagecreatefromjpeg($ path_to_90_directory。$ filename); //オリジナルがjpg形式の場合は、同じ形式で画像を作成します。 その後の圧縮に必要
    }
    //サイトから取得した正方形の画像とそれに続く圧縮の作成www.codenet.ru
    // 90x90の正方形を作成します
    // dest-結果の画像
    // w-画像の幅
    //比率-アスペクト比
    $ w = 90; //正方形の90x90。 他のサイズも提供できます。
    //に基づいて元の画像を作成します
    //ソースファイルとそのサイズを決定します
    $ w_src = imagesx($ im); //幅を計算します
    $ h_src = imagesy($ im); //画像の高さを計算します
    //空の正方形の画像を作成します
    //それはtruecolorです!これは重要です!そうでない場合、8ビットの結果になります
    $ dest = imagecreatetruecolor($ w、$ w);
    //写真が水平の場合、xの正方形の中心を切り取ります
    if($ w_src> $ h_src)
    imagecopyresampled($ dest、$ im、0、0、
    ラウンド((max($ w_src、$ h_src)-min($ w_src、$ h_src))/ 2)、
    0、$ w、$ w、min($ w_src、$ h_src)、min($ w_src、$ h_src));
    // yで正方形の上部を切り取り、
    //写真が垂直の場合(中央も可能ですが)
    if($ w_src<$h_src)
    imagecopyresampled($ dest、$ im、0、0、0、0、$ w、$ w、
    min($ w_src、$ h_src)、min($ w_src、$ h_src));
    //正方形の画像は切り抜きなしで拡大縮小されます
    if($ w_src == $ h_src)
    imagecopyresampled($ dest、$ im、0、0、0、0、$ w、$ w、$ w_src、$ w_src);
    $日付=時間(); //現時点での時間を計算します。
    imagejpeg($ dest、$ path_to_90_directory。$ date。 "。jpg"); // jpg画像を目的のフォルダに保存します。名前は、現在の時刻になります。 アバターが同じ名前にならないように作られました。
    //なぜjpg? それは非常に小さなスペースを占有します+ユーザーの気を散らすgif画像のアニメーションは破壊されます。 目の隅からの動きに気づいたときに彼の解説を読むのはあまり楽しいことではありません。
    $ avatar = $ path_to_90_directory。$ date。 "。jpg"; //変数にアバターへのパスを入力します。
    $ delfull = $ path_to_90_directory。$ファイル名;
    unlink($ delfull); //元のアップロードされた画像を削除します。不要になりました。 仕事はミニチュアを手に入れることでした。
    }
    そうしないと
    {
    //形式が一致しない場合は、適切なメッセージを発行します
    exit( "アバターは次の形式である必要があります JPG、GIFまたはPNG");
    }
    //ロードプロセスが終了し、$アバター変数をロードされたアバターのアドレスに割り当てます
    }



    //新しいものを追加しました*******************************************
    //次に、記事の最初の部分からすべてが続きますが、データベースへのリクエストに変更を追加する必要があります。
    //データベースに接続します
    //同じログインのユーザーの存在を確認します
    $ result = mysql_query( "SELECT id FROM users WHERE login =" $ login ""、$ db);
    if(!empty($ myrow ["id"]))(
    exit( "申し訳ありませんが、入力したユーザー名は既に登録されています。別のユーザー名を入力してください。");
    }
    //そうでない場合は、データを保存します
    $ result2 = mysql_query( "INSERT INTO users(login、password、avatar)VALUES(" $ login "、" $ password "、" $ avatar ")");
    //エラーがあるかどうかを確認します
    if($ result2 == "TRUE")
    {
    echo "登録に成功しました!これでサイトにアクセスできます。ホームページ";
    }
    そうしないと (
    echo "エラー!あなたは登録されていません。";
    }
    ?>

    4.同じデータベースに1つのテーブルを追加する必要があります。 入力時に間違えたIPアドレスを保存します。 これにより、15分間連続で3回以上間違えた人のアクセスを制限することができます。パスワードを推測するプログラムは、長い間いじくり回さなければならないと思います。
    phpmyadminに移動し、3つのフィールドを持つ新しいテーブルを作成します。


    ip-ip-address。
    date-指定されたIPを持つユーザーの過去15分間のログインの失敗の日付。 col-指定されたIPを持つユーザーの過去15分間のエラー数。
    罰金! これで、パスワードが暗号化されたので、ログインとパスワードの確認ファイルを変更しましょう。 testreg.phpを開き、ログインとパスワードからスペースを削除する以外のすべてを削除します。 次に、次のコードを追加します。

    //余分なスペースを削除します
    $ login = trim($ login);
    $ password = trim($ password);

    //新しいものと交換します*******************************************
    //データベースに接続します
    include( "bd.php"); // bd.phpファイルは他のすべてのフォルダーと同じフォルダーにある必要があります。そうでない場合は、パスを変更するだけです。
    //パスワード推測のミニチェック
    $ ip = getenv( "HTTP_X_FORWARDED_FOR");
    if(empty($ ip)|| $ ip == "unknown")($ ip = getenv( "REMOTE_ADDR");)// IPを取得
    mysql_query( "DELETE FROM oshibka WHERE UNIX_TIMESTAMP()-UNIX_TIMESTAMP(date)> 900"); // 15分後にエラーでログインしたユーザーのIPアドレスを削除します。
    $ result = mysql_query( "SELECT col FROM oshibka WHERE ip =" $ ip ""、$ db); //指定されたIPを持つユーザーの最後の15回の失敗したログイン試行の数をデータベースから取得します
    $ myrow = mysql_fetch_array($ result);
    if($ myrow ["col"]> 2)(
    // 3つ以上のエラー(3つ)がある場合は、メッセージを発行します。
    exit( "ログインまたはパスワードを3回間違って入力しました。次の試行まで15分待ちます。");
    }
    $ password = md5($ password); //パスワードを暗号化する
    $ password = strrev($ password); //安全のためにリバースを追加します
    $ password = $ password。 "b3p6f";
    //たとえば、「b3p6f」と入力すると、好みに合わせて独自の文字をいくつか追加できます。 このパスワードが同じmd5を使用する独自のサーバーで強引な方法で解読された場合、明らかに良いことは何も起こりません。 ただし、他の文字を配置することをお勧めします。行の先頭または途中に配置できます。
    //この場合、データベースのパスワードフィールドの長さを増やす必要があります。 暗号化されたパスワードははるかに大きくなる可能性があります。

    $ result = mysql_query( "SELECT * FROM users WHERE login =" $ login "AND password =" $ password ""、$ db); //入力したユーザー名とパスワードを持つユーザーに関するすべてのデータをデータベースから取得します
    $ myrow = mysql_fetch_array($ result);
    if(empty($ myrow ["id"]))
    {
    //入力したユーザー名とパスワードを持つユーザーが存在しない場合
    //指定されたIPを入力できなかったことをメモします。
    $ select = mysql_query( "SELECT ip FROM oshibka WHERE ip =" $ ip "");
    $ tmp = mysql_fetch_row($ select);
    if($ ip == $ tmp)(//ユーザーが「oshibka」テーブルにいるかどうかを確認します
    $ result52 = mysql_query( "SELECT col FROM oshibka WHERE ip =" $ ip ""、$ db);
    $ myrow52 = mysql_fetch_array($ result52);
    $ col = $ myrow52 + 1; //失敗したログイン試行をもう1つ追加します
    mysql_query( "UPDATE oshibka SET col = $ col、date = NOW()WHERE ip =" $ ip "");
    }
    そうしないと (
    mysql_query( "INSERT INTO oshibka(ip、date、col)VALUES(" $ ip "、NOW()、" 1 ")");
    //過去15分間にエラーがなかった場合は、「oshibka」テーブルに新しいレコードを挿入します
    }

    exit( "申し訳ありませんが、入力したユーザー名またはパスワードが正しくありません。");
    }
    そうしないと (
    nbsp; //パスワードが一致する場合、ユーザーのセッションを開始します! あなたは彼を祝福することができます、彼は入りました!
    $ _SESSION ["password"] = $ myrow ["password"];
    $ _SESSION ["login"] = $ myrow ["login"];
    $ _SESSION ["id"] = $ myrow ["id"]; //このデータは非常に頻繁に使用されるため、ログインしたユーザーは「彼と一緒に」移動します

    //次に、後続のログインのために、Cookie内のデータを記憶します。
    //注意!!! データは暗号化なしでCookieに保存されるため、自由に使用してください
    if($ _POST ["save"] == 1)(
    //ユーザーが次回のログインのためにデータを保存したい場合は、ブラウザのCookieに保存します
    setcookie( "login"、$ _POST ["login"]、time()+ 9999999);
    setcookie( "password"、$ _POST ["password"]、time()+ 9999999);
    }}
    エコー " "; //ユーザーをメインページにリダイレクトすると、ログインが成功したことが通知されます
    ?>

    5.メインページを完全に変更します。 ユーザーのアバターを表示し、アカウントからログアウトするためのリンクを表示し、ログイン時にパスワードを記憶するためのチェックボックスを追加する必要があります。
    Index.php

    //プロシージャ全体がセッションで機能します。 ユーザーがサイトにいる間、ユーザーのデータが保存されるのはその中にあります。 ページの最初で実行することが非常に重要です!!!
    session_start();
    include( "bd.php"); // bd.phpファイルは他のすべての人と同じフォルダーにある必要があります。そうでない場合は、パスを変更するだけです。
    if(!empty($ _ SESSION ["login"])および!empty($ _ SESSION ["password"]))
    {
    //セッションにログインとパスワードがある場合は、それらをチェックしてアバターを取得します
    $ login = $ _SESSION ["login"];
    $ password = $ _SESSION ["password"];
    $ result = mysql_query( "SELECT id、avatar FROM users WHERE login =" $ login "AND password =" $ password ""、$ db);
    $ myrow = mysql_fetch_array($ result);
    //必要なユーザーデータを取得します
    }
    ?>


    ホームページ


    ホームページ

    if(!isset($ myrow ["avatar"])または$ myrow ["avatar"] == "")(
    //ユーザーデータがデータベースから取得されているかどうかを確認します。 そうでない場合、彼は入力しなかったか、セッションのパスワードが正しくありません。 ログインウィンドウを表示します。 ただし、入場した方には表示せず、不要になります。
    印刷<<


    ここ;

    If(isset($ _ COOKIE ["login"]))// COOKIEにログインする変数があります。 前回のログイン時にユーザーが[Rememberme]チェックボックスをクリックした場合のはずです
    {
    //はいの場合、その値をフォームに挿入します。 この場合、ユーザーには、自分のログインがすでに必要な列に入力されていることが示されます。
    echo "value =" "。$ _ COOKIE [" login "]。" ">";
    }

    印刷<<




    ここ;

    If(isset($ _ COOKIE ["password"]))// COOKIEにパスワードを持つ変数があります。 前回のログイン時にユーザーが[Rememberme]チェックボックスをクリックした場合のはずです
    {
    //はいの場合、その値をフォームに挿入します。 この場合、ユーザーには、自分のパスワードがすでに必要な列に入力されていることが示されます。
    echo "value =" "。$ _ COOKIE ["パスワード "]。" ">";
    }

    印刷<<



    私を覚えてますか。






    今すぐ登録



    ゲストとしてログインしています

    ここ;
    }
    そうしないと
    {
    //ログインに成功すると、ユーザーには以下のアスタリスクの間にすべてが表示されます。

    印刷<<
    $ _SESSION(ログアウト)としてサイトにログインしています


    このリンクは登録ユーザーのみが利用できます

    あなたのアバター:




    ここ;

    //************************************************************************************
    //ログインに成功すると、ユーザーにはアスタリスクの間にある上記のすべてが表示されます。
    }
    ?>



    6.ログインしているユーザーのアカウントからログアウトできるようにする必要があります。 メインページにはすでに終了リンクがありました。 しかし、このファイルはまだ存在していません。 それでは、新しいファイルを作成しましょう exit.phpコード付き:

    session_start();
    if(empty($ _ SESSION ["login"])またはempty($ _ SESSION ["password"]))
    {
    //ユーザー名とパスワードのセッションがない場合、ロック解除されたユーザーがこのファイルにアクセスします。 彼はここに属していません。 エラーメッセージを発行し、スクリプトを停止します
    exit( "このページへのアクセスは登録ユーザーのみに許可されています。登録されている場合は、ユーザー名とパスワードを使用してサイトにアクセスしてください
    ホームページ ");
    }

    unset($ _ SESSION ["password"]);
    unset($ _ SESSION ["login"]);
    unset($ _ SESSION ["id"]); //セッション内の変数を破棄します
    出口 (" ");
    //ユーザーをメインページに送ります。
    ?>

    以上です! あなたの健康にそれを使用してください! 幸運を!