我们有一个实用程序通过反映某些视图和存储过程的定义来执行一些SQL魔术。为此,代码需要访问表INFORMATION_SCHEMA.ROUTINES,INFORMATION_SCHEMA.VIEWS等中的各个字段。
所以我们编写了一个适用的游标
GRANT VIEW DEFINITION on ' + @Name + ' TO tenant'
其中tenant是代码执行的角色,@ Name是proc名称的游标变量。这很有效。
然后有人将不可避免地删除/重新创建一个proc,从而删除了对proc的定义的访问,导致魔术实用程序失败。
那么说“在”租户“角色下执行的所有代码都具有对所有INFORMATION_SCHEMA表的完全读取权限的最佳方式是什么?'
修改
我尝试GRANT VIEW ANY DEFINITION TO tenant
并引发了下一个错误:
无法找到登录“租户”,因为它不存在或您没有权限。
这是因为租户是角色而不是用户,还是我真的没有权限?我以sa登录。
答案 0 :(得分:4)
我不想回答我自己的问题,但这似乎有效:
GRANT VIEW DEFINITION TO tenant
这适用于数据库范围。
GRANT VIEW ANY DEFINITION TO tenant
应该在服务器范围内工作,但我得到:'找不到登录'租户',因为它不存在或者您没有权限。是因为'租户'是一个角色而不是用户?
数据库范围方法可以满足我的需求,但不是将我自己的答案标记为正确,有人可以解释为什么服务器范围版本不起作用吗?而且,这是否会带来任何真正的安全威胁?
答案 1 :(得分:3)
如果找不到更好的方法,可以使用的一种方法是在用于创建过程的脚本末尾分配权限。 e.g。
If Exists(...)
Drop Proc Foo
Create Proc Foo
As
GO
GRANT VIEW DEFINITION on Foo TO tenant
GO
答案 2 :(得分:1)
当它不是程序的初始实际CREATE时开始使用ALTER PROCEDURE ....
,这将保持权限不变。
首次创建过程时仅使用CREATE
命令,然后始终ALTER
。因此,无需删除它(并失去所有权限),每次进行更改时都会再次创建它。
修改强>
这里有一种方法可以改变你的存储过程(也适用于VIEWS)编码,这样你就可以随时使用ALTER
:
BEGIN TRY
--create a dummy procedure if it doesn't already exist
EXEC ('CREATE Procedure YourProcedure AS SELECT 1/0')
END TRY BEGIN CATCH END CATCH --ignore the error if it already exits
GO
ALTER Procedure YourProcedure --it will always exist, because of the above code
AS
SELECT 'Hello World!'
GO
这样你就可以使用ALTER
而不是IF EXITS ... DROP然后使用CREATE模式。