使用列作为变量时防止 sql "injection" 的最佳方法

Best way to prevent sql "injection" when using column as variable

我正在使用 pymssql 向 MS SQL 服务器更新、删除和添加列。可悲的是,这些列是由外部源设置的变量,例如读取数据库,从另一个数据库读取。现在我试图阻止 "bad" sql 通过,因为我不知道其他数据库到底给我什么。

'ALTER TABLE tablenameA ADD  [' + columnname + '] varchar(25) NULL'
'ALTER TABLE tablenameA DROP COLUMN ['+columnname+']'
('UPDATE tablenameA SET [' + columnname + ']=%s WHERE id = 2', value)

现在我不能使用白名单,因为我不知道要添加什么列名,我唯一能想到的其他选择是使用黑名单,但我想知道是否可能存在第三种选择。

(列名取自 table 中字符串类型的列)

Transact-SQL 具有将 SQL 字符串转换为安全对象名称的函数:QUOTENAME()。在绑定参数周围使用它,让数据库驱动程序提供正确引用的 SQL 对象:

cursor.execute('SELECT QUOTENAME(%s)', (columnname,))
quoted_columnname, = next(cursor)

现在您可以在新查询中使用 that 字符串:

query = 'ALTER TABLE tablenameA ADD {} varchar(25) NULL'.format(quoted_columnname)

等我使用 str.format() 在这里插入字符串,而不是使用字符串连接。请注意,不再需要 [...] 方括号; QUOTENAME() 处理好了。