sql >> Base de Datos >  >> RDS >> Mysql

¿Cuál es una mejor manera de hacer que este inserto sea más seguro y a salvo de la inyección y la manipulación?

Como sugieren los comentarios anteriores, vale la pena usar parámetros de consulta para protegerse de la inyección SQL.

Usted pidió un ejemplo de cómo se podría hacer algo malicioso. De hecho, ni siquiera necesita ser malicioso. Cualquier cadena inocente que contenga legítimamente un apóstrofo podría romper su consulta SQL. La inyección SQL maliciosa se aprovecha de esa debilidad.

La debilidad se soluciona manteniendo los valores dinámicos separados de su consulta SQL hasta que se analiza la consulta. Usamos marcadores de posición de parámetros de consulta en la cadena SQL, luego usamos prepare() para analizarlo, y luego combine los valores cuando execute() la consulta preparada. De esa manera permanece seguro.

Así es como escribiría su función. Supongo que usaré PDO que admite parámetros de consulta con nombre. Recomiendo usar PDO en lugar de Mysqli.

function updateProfile( $vars, $userId ) {
    $db = new Database();
    $safeArray = [
        "gradYear",
        "emailAddress",
        "token",
        "iosToken",
        "country",
        "birthYear",
        "userDescription",
    ];
    // Filter $vars to include only keys that exist in $safeArray.
    $data = array_intersect_keys($vars, array_flip($safeArray));

    // This might result in an empty array if none of the $vars keys were valid.
    if (count($data) == 0) {
        trigger_error("Error: no valid columns named in: ".print_r($vars, true));
        $response = ["response" => 400, "title" => "no valid fields found"];
        return $response;
    }
    
    // Build list of update assignments for SET clause using query parameters.
    // Remember to use back-ticks around column names, in case one conflicts with an SQL reserved keyword.
    $updateAssignments = array_map(function($column) { return "`$column` = :$column"; }, array_keys($data));
    $updateString = implode(",", $updateAssignments);

    // Add parameter for WHERE clause to $data. 
    // This must be added after $data is used to build the update assignments.
    $data["userIdWhere"] = $userId;
    
    $sqlStatement = "update users set $updateString where userId = :userIdWhere";

    $stmt = $db->prepare($sqlStatement);
    if ($stmt === false) {
        $err = $db->errorInfo();
        trigger_error("Error: {$err[2]} preparing SQL query: $sqlStatement");
        $response = ["response" => 500, "title" => "database error, please report it to the site administrator"];
        return $response;
    }
    
    $ok = $stmt->execute($data);
    if ($ok === false) {
        $err = $stmt->errorInfo();
        trigger_error("Error: {$err[2]} executing SQL query: $sqlStatement");
        $response = ["response" => 500, "title" => "database error, please report it to the site administrator"];
        return $response;
    }

    $response = ["response" => 200, "title" => "update successful"];
    return $response;
}