不做任何修改直接将用户输入插入 SQL 查询会使应用程序容易受到 SQL 注入攻击。为了防止这种情况发生,将数据与 SQL 分离以确保数据保留为数据并且永远不会被 SQL 解析器解释为命令。
最有效的解决方案
避免 SQL 注入攻击的推荐方法,无论使用什么数据库,都是使用 准备好的语句和参数化查询。这些是由数据库服务器独立解析的 SQL 语句以及参数。这种方法使攻击者无法注入恶意 SQL。
使用 PDO 或 MySQLi 实现
PDO 为所有受支持的数据库驱动程序提供通用解决方案,而 MySQLi 是特定的到 MySQL。
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name'); $stmt->execute(['name' => $name]); foreach ($stmt as $row) { // Do something with $row }
$result = $db->execute_query('SELECT * FROM employees WHERE name = ?', [$name]); while ($row = $result->fetch_assoc()) { // Do something with $row }
$stmt = $db->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); // 's' specifies string type $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // Do something with $row }
正确的连接设置
当使用 PDO for MySQL 时,请通过禁用来确保使用真正的准备好的语句
$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8mb4', 'user', 'password'); $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
对于 MySQLi,使用以下内容:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // error reporting $dbConnection = new mysqli('127.0.0.1', 'username', 'password', 'test'); $dbConnection->set_charset('utf8mb4'); // charset
说明
准备好的语句由数据库服务器解析和编译,将 SQL 语句与参数分开。参数传递时,会以字符串形式与编译后的语句组合在一起,消除 SQL 注入的风险。
动态查询
Prepared statements 可用于动态查询中的参数,动态查询结构本身不能参数化。在这些情况下,建议使用白名单过滤器。
以上是如何有效防止PHP应用中的SQL注入?的详细内容。更多信息请关注PHP中文网其他相关文章!