対象読者
はじめに
register_globals
変数はどのようにして PHP に取得されるのですか?
URL から
フォームから
Cookie から
環境またはサーバーから
スーパーグローバルを使用してください!
スーパーグローバルと呼ばれる理由?
その他のコーディング手法
ハッキング方法
概要
著者について
対象読者
PHP 4.2.0 より前では、PHP 設定パラメータ register_globals のデフォルト値は On でした。多くの PHP プログラマーが、この構成が提供する使いやすさを利用しました。
この記事は、これまで register_globals On に依存していて、現在はコーディング スタイルを変更して、新しいデフォルトを反映したいと考えている PHP プログラマーを対象としています。このパラメータ。また、PHP 構成ファイルの値を制御できない、ISP がホストする PHP 環境を使用するプログラマーにとっても興味深いものになります。
はじめに
私は、PHP の強みの 1 つは学習曲線の容易さであると考えています。 PHP では、PHP の一部を HTML ファイルに埋め込むことができるため、HTML 作成者はこの言語に容易に慣れることができます。 PHP は非常に C に似た構文を備えているため、C に慣れているプログラマーでも簡単に移行できます。弱い変数の型指定、PHP の多くの拡張機能の柔軟性と強力さ、インターネット上の豊富な例や記事も、PHP の学習を容易にするのに貢献しています。
PHP の最近の変更により、学習曲線が若干長くなる可能性があります。 PHP 4.2.0 のリリースにより、 register_globals のデフォルト値は Off になりました。これにより、PHP の学習を容易にする機能の 1 つが失われます (この問題を修正することがこの記事の目的です)。
なぜこれが行われたのですか?一言で言えば、セキュリティです。初期化してソース内の各変数がどこから来たのかを把握すると、コードは本質的により安定します。ユーザーから入力を受け取るときは常に注意が必要であり、コード内でユーザーが任意に変数を作成できるようにすることは、良いコーディング手法ではありません。これについては、http://www.php.net/release_4_1_0.php (「セキュリティ: 新しい入力メカニズム」というタイトルのセクションを参照) および http://www.php.net/manual/en/ で PHP 開発者自身が詳しく説明していると思われます。 security.registerglobals.php。
register_globals
register_globals 設定パラメータは、php.ini ファイルで制御されます。設定ファイルの詳細については、http://www.php.net/manual/en/configuration.php を参照してください。 register_globals パラメータ http://www.php.net/manual/en/configuration.php#ini.register-globals は、On または Off の 2 つの値を取ることができます。 PHP バージョン 4.2 より前は、On がデフォルトでしたが、現在は変更されており、この変更に対応するためにコーディングを変更することがこの記事の主題です。
変数はどのようにして PHP に取り込まれるのですか?
URL を使用した経験のある PHP プログラマークエリ パラメーター、フォーム、および Cookie は、このセクションが冗長であると判断するため、スーパーグローバルに関するセクションに直接移動することをお勧めします。
変数は多くのソースから取得されます。ソースが自分で初期化すると、$var = 'value'; になります。次のセクションでは、URL、フォーム、Cookie、またはサーバーが実行される環境の一部として変数をスクリプトに取り込む他のいくつかの方法について説明します。これらの例は、サーバーが実行する環境の一部として説明されています。 register_globals をオンにし、register_globals をオフにしてこれらの値を取得する方法と場所については記事の後半で説明します。
URL から
情報を取得する最も一般的な方法の 1 つは、クエリ パラメーターを渡すことです。以下は URL の構造です (PHP での URL の解析の詳細については、 http://www.php.net/manual/en/function.parse-url.php を参照してください):
スキームは、クライアントとサーバーがリクエストに使用するプロトコル。 Http と https は最も一般的に使用されるプロトコルですが、ftp などの別のプロトコルを指定することもできます。
基本的な HTTP 認証のユーザーとパスワードの情報は、URL の一部として渡すことができます。
ホストは、この URL によって参照されるサーバーの IP アドレスまたは DNS 名です。
ポートはサーバーで使用する TCP/IP ポートです。80 は HTTP の標準、443 は HTTPS の標準です。
パスはサーバー上のスクリプトの場所と名前です。
クエリは URL によって渡されるパラメータです。
Fragment は HTML ドキュメント内のスクロール ターゲットです。
ここで最も関心のある URL の部分は、クエリ パラメーターの部分です。 register_globals をオンにすると、script.php は自動的に $var = 'val'; になります。 $foo = 'バー';アクセスするスクリプトのグローバル変数として設定します。
スクリプトの URL でクエリ パラメーターが指定されるたびに、PHP は $HTTP_GET_VARS というグローバル配列を作成します。これはキー => の連想配列です。 URL クエリ パラメーターからの値のペア。上記の例から、PHP は $HTTP_GET_VARS = array ('var' => 'val', 'foo' => 'bar'); を自動的に作成します。
PHP 4.1.0 以降、$_GET というグローバル変数には $HTTP_GET_VARS と同じ配列が含まれます。この配列はスーパーグローバルであり、この記事の後半で詳しく説明します。
フォームから
スクリプトに入力変数を取得するもう 1 つの非常に一般的な方法は、Web ページ上のフォームからです。以下に、HTML ソースを含む Web ページがどのようにレンダリングされるかを示す例を示します。
ユーザーが「送信!」をクリックしたときボタンをクリックすると、ブラウザーはユーザーが Web フォーム上のテキスト ボックスに入力した値を持つ $foo というポスト変数を使用してフォームを script.php に送信します。 register_globals がオンの場合、script.php には $foo = 'bar'; が含まれます。デフォルトでグローバル変数として使用できます。
クエリパラメータの例と同様に、ブラウザが PHP スクリプトにフォームを送信するたびに、PHP は $HTTP_POST_VARS を key => の連想配列として自動的に作成します。すべてのフォーム入力の値のペア。上記の例では、$HTTP_POST_VARS['foo'] = 'bar'; が自動的に作成されます。
PHP 4.1.0 以降では、変数 $_POST に同じ連想配列が含まれます。
Cookie から
Web ページは本質的にステートレスです。つまり、Web ページが取得されるたびに、渡された情報を使用して生成されます。リクエスト。この事実は、初期の Web 開発にとって課題となっていました。デザイナーは、ユーザーとの対話全体、おそらくサイト上の多くの Web ページ リクエストにわたって状態を維持したいと考えていました。 Cookie の概念は、ユーザーの現在のブラウジング セッション中、およびユーザーのハード ドライブに Cookie を「ドロップ」することで長期間にわたって、この状態を維持するために必要な情報を渡すために開発されました。
次のコードが配置された場合スクリプトでは、他の出力が送信される前に Cookie が設定されます:
/* Set Cookie for 1 day */
setcookie('foo', 'bar', time()+86400, '', $HTTP_HOST );
注: 鋭い観察者は、例で使用されている $HTTP_HOST に古いグローバル変数があることに気づくでしょう。 register_globals = 'off' の場合、これは $_SERVER['HTTP_HOST'] である必要があります。
このページ上の同じサーバーへのリンクは $foo = 'bar'; を渡します。
環境またはサーバーから
オペレーティング システム環境と Web サーバーには、スクリプトで使用できる多くの変数があります。サーバー変数の最も一般的な使用法の 1 つは、スクリプト自体の名前、または上記の例のようにホストの名前を取得することです。
PHP は、$HTTP_ENV_VARS および $HTTP_SERVER_VARS として追加の連想配列を作成します。 PHP 4.1.0 以降では、これらの同じ配列が $_ENV と $_SERVER で定義されます。
スーパーグローバルを使用してください!
これで、これらの変数がどのように PHP に取得されるか、そして register_globals の実行時に PHP によって自動的に作成されないことが理解できました。オフに設定した場合、新しいデフォルトに合わせてコーディング スタイルで何ができるかを特定します。
最初の選択肢は、新しいスーパーグローバル配列を使用することです。結局のところ、それがそのために追加されたものだからです。これは、特にスクリプト内で値を 1 回だけ使用する場合 (print 'Your IP Address is:' . $_SERVER['REMOTE_ADDR']; ) には、推奨される方法です。
さらに値を使用する場合毎回明示的にスーパーグローバルを参照する代わりに、値を変数に割り当てることができます ($mode = $_GET['mode']; )。
なぜスーパーグローバルと呼ばれるのですか?
通常、関数で使用される変数はどれもはその関数のスコープ内でローカルです。これは、関数でグローバル $HTTP_GET_VARS 配列値を使用したい場合は、最初にステートメント global $HTTP_GET_VARS; を使用する必要があることを意味します。
スーパーグローバルは、このルールの例外です。変数 $_GET、$_POST、$_COOKIE、$_ENV、$_SERVER、$_SESSION は、最初にグローバルとして参照しなくても使用できます。追加のスーパーグローバル配列 $_REQUEST も 1 つあります。この配列には、GET、POST、または COOKIE メソッドからのすべての変数が含まれます (基本的に、ユーザーによって送信される可能性があるため、疑わしいものはすべて)。
注: 変数変数を使用して関数内のスーパーグローバル配列にアクセスすることはできません。たとえば、次のコードは機能しません:
function foo()
{
$sg = ’_GET’;
${$sg}[$var]を返します;
}
?>
上記の foo() 関数は $_GET スーパーグローバル配列からの値を返しません。
その他のコーディング手法
変数を登録する簡単な方法に戻りたいと思うようになりました。ただし、セキュリティのリスクを承知して、移行を容易にするために代わりにいくつかのヘルパー関数を作成しました。
私が最初に作成した関数は register() :
/**
* グローバル配列から値を返す
*
* @著者 Jason E. Sweat
* @since 2002-02-05
* @param string $varname
* 登録する変数の名前
*
* @param string $defval オプション
* 見つからない場合に返す値
*
* @return string
* が登録されている場合の変数の値、それ以外の場合はデフォルトの
*/
function register($varname, $defval=NULL)
{
if (array_key_exists($varname, $_SERVER)) {
$retval = $_SERVER[$varname];
} elseif (array_key_exists($varname, $_COOKIE)) {
$retval = $_COOKIE[$varname];
} elseif (array_key_exists($varname, $_POST)) {
$retval = $_POST[$varname];
} elseif (array_key_exists($varname, $_GET)) {
$retval = $_GET[$varname];
} elseif (array_key_exists($varname, $_ENV)) {
$retval = $_ENV[$varname];
} else {
$retval = $defval;
}
return $retval;
}
?>
この関数を使用すると、スクリプトに渡されると予想される変数を「登録」できるようになりました。通常は $mode = register('mode'); を実行してこれを使用します。この関数は、php.ini ファイル (http://www.php.net/manual/en/configuration.php#ini.variables-order ) のデフォルトの variables_order パラメーターに従うように定義されているため、同じ結果を返します。 register_globals をオンにした PHP (登録しているのと同じ名前の変数に割り当てられている場合)。この関数では、スーパーグローバル配列のいずれにも値が見つからない場合に変数を初期化するデフォルト値を指定することもできます。
この関数には 1 つの欠点がありました。常に値を返すため、常に値が返されます。変数を何かに初期化します。コード内に、値が渡されたかどうかを判断するために isset() を使用したいインスタンスがいくつかありました。この動作に対応するために、別の関数を使用して値を登録しました。
/**
* 指定された get
* または post var が存在する場合はグローバル変数を設定します
*
* @author Jason E. Sweat
* @since 2002-04-25
* @param string $test_vars
* 変数の配列
* register は文字列を受け入れます
* 単一の変数の名前も受け入れます
*
* @global 変数が設定されている場合
*/
function getpost_ifset($test_vars)
{
if (!is_array($test_vars) ) {
$test_vars = 配列($test_vars);
}
foreach($test_vars as $test_var) {
if (isset($_POST[$test_var])) {
global $$test_var;
$$test_var = $_POST[$test_var];
} elseif (isset($_GET[$test_var])) {
グローバル $$test_var;
$$test_var = $_GET[$test_var];
}
}
}
?>
この関数を使用すると、登録する変数の文字列の配列を渡すことができます。変数が GET メソッドまたは POST メソッドで渡された場合、それらはグローバル値として設定されます。そうでない場合でも、isset() を使用して値が渡されたかどうかを確認できます。
この関数は、値の配列を簡単に初期化できるため、フォーム ハンドラー スクリプトを作成するのにも特に適しています (getpost_ifset(array('username', 'password', 'password2')); )。
ハッキングの方法
「時間が足りない」「プログラムはサードパーティのコードなので、学習したり保守したくない」という言い訳がすでに聞こえてきます。
register_globals Off のデフォルト値を回避する必要がある場合は、import_request_variables() 関数 (http://www.php.net/manual/en/function.import-request-variables.php) を読むことをお勧めします。 ) または、extract() 関数 (http://www.php.net/manual/en/function.extract.php) に関連する読者投稿コメントの一部を確認してください。 PHP スクリプトに変数を取り込む手段と、 register_globals のデフォルトのオンからオフへの変更に対応するために利用できるさまざまなコーディング方法です。幸運を祈ります。そして、幸せな (そして安全な) コーディングをしてください!
著者について
ジェイソンは、1992 年にコロラド州立大学を卒業して以来、IT プロフェッショナルとして働いてきました。彼は現在、アプリケーション開発者であり、Web マスターを務めています。は、フォーチュン 100 企業の事業部門であり、教育および家庭用ビジネスの目的で自宅にサーバーを維持しています。彼は現在、妻と 2 人の子供とともにアイオワ州に住んでいます。コメントやご質問がございましたら、以下に投稿するか、jsweat_php@yahoo.com までお気軽にお送りください。