接收到“对对象的SELECT权限被拒绝”,即使已被授予


11

我是程序员,而不是dba。。。我知道足够危险了。

我继承了一个旧用户,该旧用户是该数据库的db_owner。出于业务原因,我们无法调整该用户对现有表,模式等的权限,但是正在创建一些新表,我只希望该用户对其具有SELECT访问权限。

已为这些用户设置了这些表的权限,以便除SELECT(设置为GRANT)以外的所有内容都被拒绝。

但是,当此用户(dbadmin)尝试对这些表之一(AccountingAudit)执行SELECT时,会发生此错误:

The SELECT permission was denied on the object 'AccountingAudit', database 'billing', schema 'dbo'.

我已经运行此SQL来尝试查看为此表/用户设置了哪些权限:

select object_name(major_id) as object,
 user_name(grantee_principal_id) as grantee,
 user_name(grantor_principal_id) as grantor,
 permission_name,
 state_desc
from sys.database_permissions

这就是我得到的:

AccountingAudit dbadmin dbo ALTER   DENY
AccountingAudit dbadmin dbo CONTROL DENY
AccountingAudit dbadmin dbo DELETE  DENY
AccountingAudit dbadmin dbo INSERT  DENY
AccountingAudit dbadmin dbo REFERENCES  DENY
AccountingAudit dbadmin dbo SELECT  GRANT
AccountingAudit dbadmin dbo TAKE OWNERSHIP  DENY
AccountingAudit dbadmin dbo UPDATE  DENY
AccountingAudit dbadmin dbo VIEW DEFINITION DENY
AccountingAudit dbadmin dbo VIEW CHANGE TRACKING    DENY

似乎应该正常工作?

我正在进行的SELECT调用是SSMS内部非常基本的SELECT * FROM AccountingAudit。我没有做任何特殊的sp_executesql或类似的事情。

我尝试过明确授予权限:

GRANT SELECT ON [dbo].AccountingAudit TO dbadmin

这没有任何效果(为什么,上面的查询已经显示它已被授予!;-)

我已经搜索了stackoverflow.com和其他地方,但是找不到我还没有尝试过的东西。我想知道它是否与架构的设置有关。(目前,我对模式知之甚少。)

有任何想法吗?谢谢!

Answers:


10

我不确定在这里,但我会一脚走出去。我认为您的问题可能出在您的DENY CONTROL记录上。大约在页面中间的一半处看这里

拒绝对数据库的CONTROL权限将隐式拒绝对数据库的CONNECT权限。被拒绝对数据库具有CONTROL权限的主体将无法连接到该数据库。

我意识到该示例是针对数据库的,但又将其作为一个粒度级别。我猜,DENY CONTROL表上的A 会拒绝对此表的所有特权。做一个REVOKE CONTROL摆脱它,看看是否能解决您的问题。

如果是这样,则必须将用户置于数据库角色或拒绝他们对表的显式特权。


1
谢谢!最初,我在实验中确实发现,如果不拒绝CONTROL,则可以进行SELECT。但是在阅读BOL时,我错误地认为这意味着我向用户提供了对该表的完全控制权。现在,我知道只要不拒绝它们的CONTROL,我仍然可以将其他权限(INSERT,DELETE等)保持在DENY级别,并达到所需的权限级别。谢谢!
Mason G. Zhwiti 2011年

尽管我没有解决我的问题,但我认为这是一个微妙之处,我觉得大多数人都会忽略。另外,我发现如果使用Active Directory组,如果更改了组成员身份,则repadmin / syncall不一定能解决问题,而我发现重新启动服务器可以解决此问题。虽然如此,仍在寻找更少的大锤方法。
John Zabroski

0
  1. 使用Ken Fisher的sp_DBPermissions存储过程查看权限。

    1. 确保选中DENY CONTROL并不适用于该表中,除了常见的DENY SELECTDENY INSERTDENY UPDATEDENY DELETEDENY REFERENCES
    2. 如果该SELECT语句包含表值函数,请确保EXECUTE AS OWNER表值函数GRANT EXECUTE上有一个或在其上(并且没有DENY EXECUTE!)。如果是这种情况,请更仔细地阅读错误消息,因为它可能不会说对表的SELECT权限被拒绝,而是对EXECUTE的拒绝。
  2. 如果用户是AD用户或组,请使用以下脚本确定用户的身份login_token

EXECUTE AS LOGIN = 'EXAMPLEDOMAIN\JOHN.DOE';
SELECT * FROM sys.login_token;
REVERT;
  1. 查看实际的执行计划。如果错误是在带有的存储过程中SET NOCOUNT ON;,则实际的执行计划将使您仅通过查看SSMS中的“消息”选项卡就可能不会关注您,因为“受影响的行”可能不在您的控制范围内。

    1. 查找触发器或临时表。
  2. 您可以将语句编译为存储过程和SSMS“查看对象依赖关系”,以及Svetlana Golovko概述的技巧,以不同的方式查找SQL Server对象依赖关系

  3. 使用SQL Server Profiler安全事件“审核架构对象访问事件”以及“ TextData”和“成功”列来跟踪SQL Server正在评估其权限的对象。-我看到了针对该事件发出两行的情况,其中一个值表示Success = 1,而另一个值表示Success = 0。在这种情况下,我发现唯一可行的解​​决方案是重新启动服务器。即使运行repadmin /syncall也不能解决问题,启动和停止应用程序(以及连接池)也无法解决。

  4. 确定登录的有效权限:

-- '<domain>\<username>' is a domain user in the group you wish to test
EXECUTE AS LOGIN = '<domain>\<username>';
SELECT * FROM fn_my_permissions('Database.Schema.Table', 'OBJECT');
REVERT;
  1. 如果用户与AD用户或组绑定,请考虑运行repadmin /syncall以强制在活动目录中进行的所有更改在您的域控制器之间同步。-如果有人知道比较两个域控制器当前值的好方法,请告诉我。

  2. 在考虑整个系统的硬重启之前,请尝试终止该用户的所有活动连接。原因是用户从包含其组的DC​​中获取了Windows令牌。在用户获得新令牌之前,令牌不会更新-通常是先注销然后再登录。

  3. 硬重启系统。它为我工作。仍不是100%知道为什么。只有在您可以生存下来的时候,才这样做!当您进行大量非凡的交易时,请务必谨慎!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.