正在清理 MySQL 个存储过程参数

Sanitizing MySQL Stored Procedure Parameters

我正在开发一个基于输入参数值动态生成查询的存储过程。 sp 使用 mysql 中的 CONCAT() 函数来构建查询。其中一个参数允许用户输入 varchar 数据类型的搜索字符串。

mysql 中是否有类似于 php 的 mysql_real_escape_string() 的功能可以防止 sql 注入攻击?

以下是此 sp 正在执行的操作的示例:

// trying to post code. keep getting denied. not telling me why.

切勿使用 CONCAT() 函数构建查询。

使用。准备好了。报表。

PREPARE stmt1 FROM 'SELECT * FROM whatever WHERE something LIKE ?';
EXECUTE stmt1 USING @search_parameter;
DEALLOCATE PREPARE stmt1;

回复您的评论:

I agree with you, however how can you add specific parts to the prepared statement based on inputs. For example, if parameters _A and _B are available, then JOIN two additional tables and include a WHERE statement? Then know which version of the query the prepared statement is being run for to know which parameters need to be bound?

有时您必须使用条件代码块:

CREATE PROCEDURE MyProc(IN _A INT, IN _B INT)
BEGIN
  IF _A IS NOT NULL AND _B IS NOT NULL
    PREPARE stmt1 FROM 'SELECT * FROM MyTable WHERE A = ? AND B = ?';
    SET @A = _A, @B = _B;
    EXECUTE stmt1 USING @A, @B;
    DEALLOCATE PREPARE stmt1;
  ELSEIF _A IS NOT NULL
    PREPARE stmt1 FROM 'SELECT * FROM MyTable WHERE A = ?';
    SET @A = _A;
    EXECUTE stmt1 USING @A;
    DEALLOCATE PREPARE stmt1;
  ELSEIF _B IS NOT NULL
    PREPARE stmt1 FROM 'SELECT * FROM MyTable WHERE B = ?';
    SET @B = _B;
    EXECUTE stmt1 USING @B;
    DEALLOCATE PREPARE stmt1;
  END
END

对于带有条件 LIMIT 和 OFFSET 的示例,您可以更简单地完成。受限于 INT 数据类型的输入参数没有 SQL 注入风险。然后,您可以使用 COALESCE().

为变量默认一些合理的值
CREATE PROCEDURE MyProc(INT _quick_search VARCHAR(50),
  IN _limit INT, IN _offset INT)
BEGIN
  SET @LIMIT = COALESCE(_limit, 1);
  SET @OFFSET = COALESCE(_offset, 0);

  PREPARE stmt1 FROM 'SELECT ...blah blah... LIMIT ? OFFSET ?';
  EXECUTE stmt1 USING @LIMIT, @OFFSET;
  DEALLOCATE PREPARE stmt1;
END

我同意@YourCommonSense 的说法,即存储过程不是最佳解决方案。 MySQL 对存储过程的实现是原始的并且难以使用。我在 Stack Overflow 上看到很多问题,询问有关如何在 MySQL 中的存储过程中执行某些任务的问题,这让我每次都感到畏缩。

您最好使用几乎任何其他脚本语言,而不是使用 MySQL 存储过程。