0

このようなupdate_user関数を使用しても安全ですか?

function update_user($update_data) {
    global $pdo;

    $update = array();

    foreach($update_data as $field=>$data){
    $update[] = '`'. $field.'` = \''. $data.'\''; 
    }
    $query = $pdo->prepare("UPDATE users SET " . implode(', ', $update) ."WHERE user_id = " .$_SESSION['user_id']);
    $query->execute(); 
}
4

2 に答える 2

1

もちろん違います。
識別子と文字列のフォーマットが不十分です。
また、PDO を古い拡張機能と区別するプレースホルダーを使用していません。

PDO タグ wikiで、このタスクにヘルパー関数を使用する例を見つけることができます。
そこから関数を使用すると、このようにすることができます

この関数は次のように使用できます。

function update_user($allowed) {
    global $pdo;
    $allowed = array("name","surname","email","password"); // allowed fields
    $sql = "UPDATE users SET ".pdoSet($allowed,$values)." WHERE id = :id";
    $stm = $pdo->prepare($sql);
    $values["id"] = $_SESSION['user_id'];
    $stm->execute($values);
}
// usage:
update_user();

この関数は $_POST 配列から直接値を取得することに注意してください。そのため、2 つの重要な点について言及する必要があります。

  • $input_data を手動で作成する必要はありません
  • $_POST 配列に存在しないフィールド (ハッシュされたパスワードなど) がある場合は、手動でそこに追加する必要があります。

ただし、$input_data既にホワイトリストに登録されている (つまり、すべてのフィールド名がハードコードされたスクリプトで作成されている) 場合は、deceze のソリューションも使用できます。
しかし$input_data、クライアント側からのものである場合、彼のソリューションは SQL インジェクションに対して脆弱です

于 2013-03-03T13:43:26.410 に答える
-1

いいえ。準備されたステートメントの使用は無意味であり、データはエスケープされません。次のように適切に準備されたステートメントを使用します。

$fields = array_map(function ($key) { return "`$key` = :$key"; }, array_keys($update_data));
$query  = sprintf('UPDATE users SET %s WHERE user_id = :userId', join(', ', $fields));
$stmt   = $pdo->prepare($query);

forach ($update_data as $key => $value) {
    $stmt->bindValue(":$key", $value);
}
$stmt->bindParam(':userId', $_SESSION['user_id']);

$stmt->execute();

これは、少なくとも配列キーがホワイトリストに登録された値であり、構文の問題を引き起こさないことを前提としています。

于 2013-03-03T13:46:23.223 に答える