2017-10-18 2 views
3

問題: 私の仕事は、さまざまな製品に関する情報を保持し、この情報を提供および管理するRESTful APIを作成するデータベースを作成することです。しかし、クライアントはこれらの製品に必要なすべての情報を正確に把握していないため、後で新しい製品のプロパティに対応するためにデータベースに新しい列とテーブルが追加される可能性があります。私の質問は、これらの変更をすぐに受け入れるデータベースを作成し、少しでも変更しなくてもまだ存在しない製品プロパティに基づいて製品を安全にフェッチできるクエリを構築することです。動的準備文を使用した安全で拡張性のあるデータベース

提案された解決策: 次の構造のテストデータベースをセットアップしました。

+------------------+ 
|  item  | 
+----+------+------+ 
| id | name | cost | 
+----+------+------+ 
| 0 | test | 50 | 
+----+------+------+ 

+--------------+ 
| color  | 
+----+---------+ 
| id | val | 
+----+---------+ 
| 0 | blue | 
| 1 | purple | 
+----+---------+ 

+--------------------+ 
|  item_color | 
+---------+----------+ 
| item_id | color_id | 
+---------+----------+ 
|  0 |  0 | 
|  0 |  1 | 
+---------+----------+ 

'item'テーブルには後でカラムが追加され、さらに多くのジャンクションテーブルが追加される可能性があります。

製品の検索要求にはhttp://www.example.com/api/products?color=purple&cost=50 が必要です。私は、適切な製品を検索するために準備された文を動的に構築しています。

function column_exists($column, $pdo) { 
    $statement = $pdo -> prepare("DESCRIBE item"); 
    $statement -> execute(); 
    $columns = $statement -> fetchAll(PDO::FETCH_COLUMN); 
    $column_exists = in_array($column, $columns); 
    return $column_exists; 
} 

function table_exists($table, $pdo) { 
    $statement = $pdo -> prepare("SHOW TABLES"); 
    $statement -> execute(); 
    $tables = $statement -> fetchAll(); 
    $table_exists = in_array($table, $tables); 
    return $table_exists; 
} 

プロパティが「アイテム」テーブル内の列として、あるいはテーブルとして検出されない場合:最初のIは、プロパティが「アイテム」テーブルに含まれており、以下の機能を使用して、別のテーブル内にあるどのされるかを決定します名前を指定すると、例外がスローされます。私のコードの構文は次のようになり

プリペアドステートメント:

$sql = "SELECT * FROM item WHERE cost = :cost 
AND id IN (SELECT item_id FROM item_color 
WHERE color_id IN (SELECT id FROM color WHERE val = :color));"; 

そしてそうのように実行されるだろう、私が知りたいのは何

$statement = $pdo -> prepare($sql); 
$statement -> execute(Array(":cost" => $cost, ":color" => $color)); 

私はなどの主要なボトルネックが発生しますデータベースが増え、頻繁にアクセスされますか?私の検索方法は1次SQLインジェクション攻撃に対して安全ですか?私がやっていること

を私は初歩的なデータベース設計の原理と基本的なSQLインジェクション攻撃/防御方法については読んだことがあります。私は準備されたステートメントを動的に作成することを試みましたが、私が見つけた資料は私が探しているものではありません。私は基本的なBobby Tables attackに対して私のデザインをテストしました。この質問は関連性があるのはなぜ

:私が読んだ 設計原理は、フィールドに新しいものがあまりにも柔軟性がどのように柔軟測るする方法がありませんとの分析から利益を得ることができるデータベースがあまりにも柔軟にしようとしてに対して警告しますこの例。また、準備されたステートメントは、静的テンプレートとしてのみ使用されるように意図されているようです。私がこの魅力的なものを構築するための動的な方法を見つけたら、おそらく他の初心者もそうだろうから、我々は大きなセキュリティ上の脆弱性を作り出しているかどうかを知る必要があります。最後に、これらの質問には、データベースの設計とそれに対して実行されるクエリの構造が直接関係しているため、一緒に質問しました。

詳細: php v5.6.17 mysql v5.6。35

+0

テーブルや列を推測してデータベース全体にアクセスできるという問題があると思います。 – LKKP4ThX

+0

どのような問題がありますか?これが道路のボトルネックを引き起こすと思いますか?私は実際に小切手がどのくらいのオーバーヘッドを追加しているのか分かりません。 –

+0

いいえ、セキュリティ面からです。誰かがデータベースユーザー、列のパスワードを試してみたら? – LKKP4ThX

答えて

0

私の最初の反応は、あなたが本当にSQLでJOINを使用する方法を学ぶ必要があるということです。結合操作は、SQLとリレーショナル・データにとって本当に基本的です。 JOINの代わりにサブクエリのみを使用することは、別のプログラミング言語を使用するようなものですが、ループはwhile()ループの使用を拒否しています。確かに、あなたはそれを行うことができますが、なぜですか?

$sql = "SELECT * FROM item WHERE cost = :cost 
AND id IN (SELECT item_id FROM item_color 
WHERE color_id IN (SELECT id FROM color WHERE val = :color));"; 

SQLカバー上の任意の参照やチュートリアルが参加し

$sql = " 
SELECT i.id, i.name, i.cost, c.color 
FROM item AS i 
INNER JOIN item_color AS ic ON i.id = ic.item_id 
INNER JOIN color AS c ON c.id = ic.color_id 
WHERE i.cost = :cost AND c.val = :color"; 

であるべき。

安全性に関するご質問は、SQLインジェクションに関してyes-usingのクエリパラメータが安全です。基本クエリをハードコードし、動的部分をパラメータに分離することで、安全でないデータがSQLクエリの解析を変更する可能性を排除します。

私のプレゼンテーションSQL Injection Myths and Fallacies(ビデオ:https://www.youtube.com/watch?v=VldxqTejybk)が好きかもしれません。

あなたの要件によって、MongoDBのようなドキュメントデータベースを使用したほうがいいと思います.MongoDBでは、どのドキュメントにも属性を追加できます。データベース設計に注意する必要はありませんが、設計後に属性を追加する機会が増えます。

+0

素晴らしい例をありがとう。これははるかに読みやすいクエリです。私はmysqlを使用する必要があります。このデータベース設計のアクセス層を構築するのに役立つリソースがありますか? –

+0

MySQL 5.7のJSONデータ型についてお読みください。https://dev.mysql.com/doc/refman/5.7/en/json.html –

+0

これはすばらしく見えます!残念ながら、MySQL 5.6を使用しています。 –

関連する問題