質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

1989閲覧

int型にcastし、文字列を0としてDB処理することの是非

yoshiky

総合スコア105

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

1グッド

1クリップ

投稿2016/05/19 07:47

お世話になっております。
例えばURLにあるデータが含まれていて、その値を使ってDBからSELECTする処理をする場合についてお伺いしたく投稿しました。
※タグをPHPにしましたが、考え方の話なので言語は問いません。

【前提】 user.id = 1 のリソースにアクセスする場合のURL /user/1 ↓ WHERE user.id = 1 のようなSELECT文が発行される。 テーブルのidはinteger型

このとき入力値検査として、パラメータをint型にCastして判定するのは、方法としてアリでしょうか?
具体的には下記の通りです。

  • 期待する値(数字)の場合はCastしても数字のままなので、WHERE id = 1で問題なく検索できる。
  • 期待しない、例えば文字列に変えられた場合は、Castされて0になるので、WHERE id = 0 となり、(多分結果はヒットはしないが)DBのCastエラーにはならない。

PHP

1/user/1 # (int)1 => 1のままなので WHERE id = 1 2/user/hoge # (int)hoge => 0になるので WHERE id = 0 3 4※castしない場合 5/user/hoge # WHERE id = hoge となり、DBエラーが発生

本来のCastの用途ではない気がするので、このような記述をしていいものか迷っています。
関数や正規表現で、数字と文字列を区別して処理するべきでしょうか(コードが増えるので敬遠してます。。)

皆様のご意見、または「以前こう書いてるのを見た」というような体験談でも結構です。

よろしくお願いいたします!

yodel👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

http://oshiete.goo.ne.jp/qa/8141743.html
上記を読む限り、どちらでも大丈夫そうですね。

私の中での結論は、以下の二択かなと思ってます。

・ステータスコードが400番を発行するまでしっかりサポートする
・SQLインジェクションが怖いのでサニタイズだけ行う、勝手にint型に文字列突っ込んでSQLエラーになっても知らんと突っぱねる

ソースコードを書きたくないは立派な動機足りえますので、2番をお勧めします。
コードの見通しがよくなり、不必要なバグを引き込まずにすみますし。


個人的には面倒みると決めたなら、責任持ってちゃんと最後まで見てあげた方が良いんじゃないですかね?
キャストする場面でいうと、hogeで検索したのに、勝手に0にしてQueryを発行しているわけで、
然るべきバリデートメソッドを通った上で、ステータスコード400等を発行して検索を終了すべきだと思います。

もし何もしない事を選択する場合、PHPを使う限りPDOが汎用的で強く、
$sth->bindValue(':user_id', $xxxx, PDO::PARAM_INT);
…などと値をバインドして突っ込む手法がベストプラクティスなので、自動的に0に置き換わるはずです。

投稿2016/05/19 08:32

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yoshiky

2016/05/19 09:09

ご回答ありがとうございます! > hogeで検索したのに、勝手に0にしてQueryを発行している 仰るとおりだと思います。検索結果が無いのか(status=200)、そもそもstatus=400(Bad Request)なのか、明示的に返したほうがベターですね。 bindValue、便利ですね。Codeigniterで実装しているのでActiveRecordを切り捨てられれば使いたいのですが。。
guest

0

DBアクセスする前にパラメータの検証をしたほうがいいのではないでしょうか。
11hoge1.1 も全部 1 になってしまいますよ。

投稿2016/05/19 07:56

kodai

総合スコア759

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yoshiky

2016/05/19 09:23

ご回答ありがとうございます! Castの返り値が言語により異なるため、適切に検証して処理する癖をつけようと思います。 割とよくあるHackだったら採用しようと思ったのですが、他の人が後で読んだときに、ぱっと分からないコードは書くべきではないですね。 ちなみにPHP5.6で確認したのですが、 (int)1hoge で1が返るんですね。。知りませんでした。。
guest

0

キャストしたものをそのまま使うことで無害化している、というのは聞いたことがありません。
しかし、ご利用の用途に限定すれば、間違っているとも言い切れないような・・・

ただ、キャストの戻り値という言語仕様に依存している部分はちょっと気になります。
例えば、intvalはオブジェクトを渡されると1を返します。
キャストできなかった場合はfalseを返す仕様に変更された場合には、WHERE user.id = false などになって、SQLのエラーになってしまいます。
将来も枕を高くして寝ていたいなら、パラメータはきっちり無害化してコントロールした方が安心と思います。

投稿2016/05/19 08:29

munyagu

総合スコア479

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yoshiky

2016/05/19 09:17

ご回答ありがとうございます! > キャストの戻り値という言語仕様に依存している 確かに言語に依存しますね。取り急ぎPHPで確認したのですが、1やfalseを返されると、Castするだけでは不完全ですね。 このケースでは「数字か数字以外」を判定すればいいので、手間ですが無害化する処理を挟んで対応しようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問