我使用的一些存储过程需要根据是否提供了过程输入参数来插入 WHERE 标准。为了避免潜在的注入点,我想对将成为插值标准一部分的值使用参数绑定。
由于添加到准备好的语句的标准以及要绑定的参数数量可能会因用户输入而异,因此我设计了以下方法来确定哪些变量将传递给 EXECUTE 语句。这行得通,但似乎不优雅。
CREATE PROCEDURE foo (IN mandatory INT, IN optional INT, IN optional2 VARCHAR(20))
BEGIN
SELECT
0, '', '', mandatory, optional, optional2
INTO
@params, @sql, @where, @m, @o1, @o2;
IF (@o1 > '' AND @o1 IS NOT NULL) THEN
SET @where = CONCAT(@where, ' AND field = ?');
SET @params = @params + 1;
END IF;
IF (@o2 > '' AND @o2 IS NOT NULL) THEN
SET @where = CONCAT(@where, ' AND field2 = ?');
SET @params = @params + 3;
END IF;
SET @sql = CONCAT('
SELECT id, bar FROM table
WHERE
baz = ?
', @where
);
PREPARE STMT FROM @sql;
CASE @params
WHEN 0 THEN EXECUTE STMT USING @m;
WHEN 1 THEN EXECUTE STMT USING @m, @o1;
WHEN 3 THEN EXECUTE STMT USING @m, @o2;
WHEN 4 THEN EXECUTE STMT USING @m, @o1, @o2;
END CASE;
DEALLOCATE PREPARE STMT;
END$$
我知道替代方案:
- 调用这些存储过程的二进制文件有一个函数,该函数通过正则表达式传递用户提供的字符串来尝试识别潜在的 SQL 注入。
- 给定动态数量的输入,用户定义的函数可用于动态构造 EXECUTE 语句。
但是,我想知道是否有其他人遇到过这种纯粹使用 SQL 来处理 EXECUTE 语句的动态构造的愿望。