我有一个简单的存储过程:

DELIMITER $$
CREATE PROCEDURE `findUserByName`(IN `name` VARCHAR(36))
BEGIN
  set @name = name;
  PREPARE findStmt FROM 'SELECT * FROM user WHERE name=?';
  EXECUTE findStmt USING @name;
END$$

我在PHP中使用Prepare方法调用它:

$stmt = $mysqli->prepare('CALL findUserByName(?)');
$stmt->execute([$inputName]);

关于上述代码,我有两个问题:

  1. 这个赋值语句set @name = name;看起来有些多余,我可以直接使用参数name吗?MySQL不允许我使用USING name,我也try 将参数名称更改为@name,但它不会被识别.

  2. 既然我在PHP中使用了Prepare方法,那么将参数与SQL连接起来是否安全呢?

    set @sql = CONCAT('SELECT * FROM user WHERE name=''', name, '''');
    PREPARE findStmt FROM @sql;
    EXECUTE findStmt;
    

推荐答案

  1. 不能,您不能使用局部变量作为EXECUTE的参数.我同意这很奇怪,也不令人满意,因为您必须设置一个用户定义的变量(带有@符号的类型),该变量似乎是多余的.

https://dev.mysql.com/doc/refman/8.0/en/execute.html表示:

参数值只能由用户变量提供

  1. 不,如果字符串可能包含不受信任的内容,则将字符串连接到动态SQL中是不安全的.这称为SQL注入,它是错误或数据泄露的常见来源.

    在上面的例子中,如果有人输入他们的名字"O‘Reilly",会发生什么?

    您可能会看到"使用准备好的语句"来保护您的代码免受SQL注入的建议,但是仅仅使用PREPARE并不是魔术.它不会为了使不安全的SQL变得安全而祝福它.建议应该是"使用参数".使用PREPARE来使用参数是必要的,但使其安全的重要部分是参数,而不是PREPARE.

Php相关问答推荐

PHP原始数据读取引发max_input_vars错误

Sylius php -如何将购物车传递到小枝模板(Sylius模板事件)

PHP从响应应用程序json获取文件代码和URL

如何在laravel中使用script type= text/html/script

htaccess重命名index.php以在URL中显示为SEO的友好名称

按日期向 WooCommerce 中的我的帐户订单添加过滤器

Woocommerce 相关产品按其类别或排名数学主要类别

使用用户元数据填写 woocommerce checkout 字段

无法使用 slim 的父级容器

PHP - 计算非数值数组

Composer自动加载器重复了子类的类文件路径

PHP preg_replace括号和方括号内的所有逗号

构建 [Controller] 时目标 [Interface] 不可实例化

PHP Remedy API 调用以创建附件无效的条目(使用 Postman Works!)

Symfony 自定义注销

如何为多个表的id列设置不同的值

标头内容类型:image/jpeg 无效

升级到 PHP 8.2:ksort 和 krsort 更改

如何解释 XDEBUG 日志(log)文件条目

使用 Laravel Policy 并为请求添加键和值