人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHP + PostgreSQLでクエリを実行する際に使用するpg_query_params()メソッドのプレースホルダの仕組みは、動的プレースホルダですか?それとも静的プレースホルダですか?
PHP + PostgreSQLで静的プレースホルダを利用する方法も教えて頂けますと助かります。

●質問者: 匿名質問者
●カテゴリ:コンピュータ ウェブ制作
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● 匿名回答1号
ベストアンサー

http://php.net/manual/ja/function.pg-query-params.php

pg_query_params() は PostgreSQL 7.4 以降の接続でのみ サポートされます。

http://www.postgresql.org/docs/7.4/interactive/release-7-4.html

New client-to-server protocol
The new protocol adds ..., parameter values separated from SQL commands, prepared statements available at the protocol level, and ....

また、
https://github.com/php/php-src/blob/master/ext/pgsql/pgsql.c#L1992
http://www.postgresql.org/docs/9.4/static/libpq-exec.html

PQexecParams is supported only in protocol 3.0 and later connections; it will fail when using protocol 2.0.

などからpg_query_params()はプロトコルの静的プレースホルダ対応に依存している事が推察出来き、静的プレースホルダしか対応しないと推察出来る。
したがって、7.4以降を使えば静的プレースホルダを利用出来るはず。


匿名質問者さんのコメント
動的と静的の各プレースホルダの違いは、下記の内容ですよね? 動的プレースホルダ :パラメータのバインド処理をアプリケーション側のライブラリ内で実行する 静的プレースホルダ :パラメータのバインド処理をデータベースエンジン側で実行する 動的プレースホルダだとライブラリによっては脆弱性が発生するおそれがあるため、静的プレースホルダだったらいいなーと思って質問した次第です。 ところで回答で頂いた引用のうち、後のものはURL掲載して頂いたページ内にはありませんでした。 また、推察ではなく、はっきりと記述のある情報元を引用頂けますと幸いです。

匿名回答1号さんのコメント
>> PQexecParams is supported only in protocol 3.0 and later connections; it will fail when using protocol 2.0. << これは http://www.postgresql.org/docs/9.4/static/libpq-exec.html のPQexecParamsの項のプロトタイプ宣言の後の段の2文目です。 ちなみにPQexecParamsの項の最初には >> Submits a command to the server and waits for the result, with the ability to pass parameters separately from the SQL command text. << とあります。 "to pass parameters separately"はこの関数に対してという解釈も可能ですが、"Submits a command to the server"に係ると読む方が素直だと思いますがいかがですか。 日本語訳もありました。 https://www.postgresql.jp/document/9.4/html/libpq-exec.html >> サーバにコマンドを送信し、結果を待ちます。 ただし、SQLコマンドテキストとは別にパラメータを渡すことができます。 <<

匿名質問者さんのコメント
「安全なウェブサイトの作り方」の第7版を読むことで、自己解決いたしました。 https://www.ipa.go.jp/files/000017316.pdf まずPDFの9ページ目に下記の記述があります。 >> プレースホルダに実際の値を割り当てる処理をバインドと呼びます。バインドの方式には、プレースホルダのままSQL文をコンパイルしておき、データベースエンジン側で値を割り当てる方式(静的プレースホルダ)と、アプリケーション側のデータベース接続ライブラリ内で値をエスケープ処理してプレースホルダにはめ込む方式(動的プレースホルダ)があります。静的プレースホルダは、SQLのISO/JIS規格では、準備された文(Prepared Statement)と呼ばれます。 << つまり、「静的プレースホルダ」イコール「プリペアドステートメント」です。 そしてPDFの75ページ目に下記の記述があります。 >> pg_query_params()は、プリペアドステートメントを構成するものではありませんが、プレースホルダの仕組みを持つ関数です。第2引数に、プレースホルダ(「$1」や「$2」)を含むSQL文を指定し、第3引数に実際の値を指定します。プレースホルダを利用することにより、利用者はSQL文の要素に対するエスケープ処理を別途行う必要がなくなります。 << pg_query_params()はプリペアドステートメントを構成しない、とあるので、静的プレースホルダではありません。 とすると動的プレースホルダであると判断出来ます。 引用して頂いた内容は「パラメータを分割して渡せる」など、プレースホルダの説明ではありますが、それが動的か静的(プリペアドステートメント)かについての記載はなかったかと思います。 なんにせよ、ちょっと疑わしいコメントを頂いたおかげで、自力で調べようという意欲がわきましたので、感謝いたします。

匿名回答1号さんのコメント
今更ですけど、ソース読むとクライアント側では処理してない様に読めます。 http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/interfaces/libpq/fe-exec.c;hb=HEAD

匿名質問者さんのコメント
不勉強で恐れ入りますが、このソースは何のソースで、何の言語で書かれているのでしょうか?

匿名質問者さんのコメント
http://lets.postgresql.jp/documents/tutorial/with_php/against_sql_injection/placeholder/pg_xxxx >> まずは、pg_query_params使用した場合です。1つめの引数にデータベース接続リソースを、2つめに「$1」「$2」という表記のプレースホルダを含んだSQLを、3つめにプレースホルダを置き換えるパラメータを配列の形式で指定します。当然ですが、$1、$2…の順番や個数は、パラメータのそれらと合致していなければなりません。 すぐに実行されるのであまり意識されませんが、PostgreSQLのログを参照すると、実際には無名のプリペアドステートメントが使用されているようです。 << たしかに、pg_query_params実行時は無名のプリペアドステートメントが使用されている、と書かれているサイトもありました。だとすると >> pg_query_params()は、プリペアドステートメントを構成するものではありませんが << という「安全なウェブサイトの作り方」の記載はなんなのでしょう。。

匿名回答1号さんのコメント
ソースはC言語です。 phpもC言語で書かれていて、pg_query_params()とかphpのPostgreSQL関連の関数もC言語でpgsql.cに書かれてる。 https://github.com/php/php-src/blob/master/ext/pgsql/pgsql.c で、このpgsql.cはPostgreSQLのライブラリのlibpq使ってます。そのソースのうち、クエリをサーバに送って実行する系の関数がfe-exec.cにあります。 http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/interfaces/libpq/fe-exec.c;hb=HEAD プリペアドステートメントは文字通り、命令を事前に準備するって事です。 SQLでPREPARE命令って命令文に名前付けて後で呼び出せる命令あります。 これだとサーバに送るのはSQLだけです。パラメータも後でSQL(EXECUTE命令)として送ります。 これもプリペアドステートメントの一つなのですが、結局パラメータをSQLとして送る必要があるので、セキュリティ目的には利用出来ません。 PREPARE命令じゃなくてプロトコル、サーバとのやりとりの仕方で、名前付けて後で利用する方法もあります。 この場合、命令に名前付けたり、送るパラメータはSQLとしてではなく送る事が出来ます。 そのためには、サーバとのやりとりにSQL以外も送ることが可能なプロトコル/APIじゃないと出来ません。 逆に言えば、パラメータをSQLとしてではなく送ることが出来、SQLとして解釈される余地がなくなり、セキュリティ目的に利用出来ます。 これが出来るようになったのが7.4以降のようです。 さて、pg_query_params()で使ってるPQexecParams()はほとんどこのプリペアドステートメントと同じような事をしています。 まずSQL文を送ります。ただ、送った文に名前を付けません。名前がついていないので後で利用出来ません。利用する方法がありません。 その代わり、直ぐにパラメータを送り実行します。 プロトコル的、内部的には事前にサーバにSQL文を送り、直後でもその後にパラメータを送っているので、事前に準備された文ではあります。 ただ、PQexecParams()つまりAPIとしては連続で、1度切りで直ぐに実行しなければならないと言うのは、実質的な意味では事前に準備された文とは呼べないかもしれません。 しかし、値がSQL文としてではなく、プレースホルダを使用しプロトコルとして別々に送られて、サーバ側でバインドされているのでプレースホルダとしてはほぼ静的プレースホルダです。 ただ、ISO/JIS規格としての定義が(狭い意味での)プリペアドステートメントを用いるということなら定義としては静的プレースホルダではないかもしれません。 ただ、それらは字義/定義上での問題で、それがどちらになるにせよ、それで動作や安全性が変わるわけでもなく、サーバにはSQL文とパラメータが別々に送られているので、サーバにバグがない限りは安全でしょう。 と言う所でしょうか。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ