Delphi环境下限制SQL Server查询为只读的技术咨询
自定义查询模块的SQL写入风险防控方案
一、能不能把ADOConnection或ADOQuery设成只读?
- ADOConnection本身没有直接的只读开关,但可以通过ADOQuery的属性做些限制:
- 把ADOQuery的
LockType设为ltReadOnly,再把ExecuteOptions改成eoExecuteNoRecords(只用来执行查询类操作)。但这只是客户端层面的限制,如果用户构造的SQL里带了写入语句,组件本身拦不住——毕竟最终能不能执行还是看数据库账号的权限。 - 说白了,这种方式防君子不防小人,恶意用户要是绕开组件的约束写恶意SQL,照样能执行写入操作,可靠性不高。
- 把ADOQuery的
二、SQL Server能不能把当前会话设成只读?
SQL Server没有Oracle那种直接的SET SESSION READONLY命令,但有两种办法能达到类似的会话级只读效果:
- 开启只读事务
- 在执行用户的自定义查询前,先跑一句
SET TRANSACTION READ ONLY;,开启只读事务。这时候会话里只要有写入操作(DELETE/UPDATE/INSERT这些),直接就会报错:无法在只读事务中执行数据修改语句。 - 要注意:这个设置只针对当前事务,如果用户的查询里自己写了事务提交或回滚,可能会打破这个限制;不过临时表操作在只读事务里是允许的(因为临时表存在tempdb里,不受当前数据库的只读事务约束),刚好能满足管理员用临时表的需求。
- 在执行用户的自定义查询前,先跑一句
- 临时切换到只读账号
- 虽然应用用的是统一的读写账号,但可以在执行普通用户的查询前,用
EXECUTE AS USER = '你的只读用户名';临时切换到只读权限的数据库用户,查完之后再用REVERT;切回原来的账号。 - 这种方式更彻底,只读账号本身就没写入权限,就算执行写入SQL也会被数据库直接拦下来,但得提前建好对应的只读账号,把权限配置好。
- 虽然应用用的是统一的读写账号,但可以在执行普通用户的查询前,用
三、关于关键词过滤的问题
你说的查关键词的办法确实不靠谱,恶意用户可以玩各种花样绕过去——比如大小写乱改(DeLeTe)、插注释(DELETE/**/FROM)、转编码之类的,最多只能当个辅助手段,不能靠这个当核心防护。
四、管理员和普通用户的区别处理
- 管理员用户:不用设任何只读限制,保留原来的读写权限,方便他们用临时表之类的操作。
- 普通自定义查询用户:优先用上面说的“开只读事务”或者“切换只读账号”的办法,从数据库层面拦写入操作,比客户端组件的限制靠谱多了。
内容的提问来源于stack exchange,提问作者user1937012
相关产品推荐
相关产品推荐

