正在清理 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 存储过程。
我正在开发一个基于输入参数值动态生成查询的存储过程。 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 存储过程。