【问题标题】:IS_ROLEMEMBER erroneously returns 0 for database role members?IS_ROLEMEMBER 错误地为数据库角色成员返回 0?
【发布时间】:2013-11-12 08:18:15
【问题描述】:

运行SQL Server 2012 的本地实例。

我创建了一个自定义角色:

CREATE ROLE [my_user] AUTHORIZATION [dbo]

对于我的所有用户(本地 Windows 用户和 SQL 用户),我已经为我的数据库指定了这个角色(在 User Mappings 设置下)。因此,以下查询应返回 1:

SELECT IS_ROLEMEMBER('my_user')

对于我的 Windows 身份验证用户,它确实返回 1,但只要我以 SQL 用户 身份登录,它返回 0。我已经三重检查了 SQL 用户确实有这个角色。我在这里错过了什么?

更新

进行了更多测试。这当然是奇怪的行为。我执行了这些步骤:

  1. 在我的本地SQL Server 上,我使用用户sa 创建了一个数据库test。已添加角色 my_user
  2. Management Studio 中以sa 身份登录,并将MYDOMAIN\MyUser 添加到此角色。
  3. 使用 Windows 身份验证重新登录并执行 IS_ROLEMEMBER('my_user')返回 0。
  4. 尝试使用sa(指定用户名)和Windows 用户进行查询。同样的问题。
  5. 尝试重启SQL Server,以防万一。

这毫无意义!如果我右键单击该角色,我可以看到我的 Windows 用户确实是其中的成员。 IS_ROLEMEMBER 函数有缺陷!当我运行以下查询时,它表明我的用户确实是数据库角色的成员:

SELECT
    USER_NAME(memberuid), USER_NAME(groupuid)
FROM
    sys.sysmembers
WHERE
    USER_NAME(groupuid) = 'my_user'

这也显示了我的会员资格:

select r.name as role_name, m.name as member_name from sys.database_role_members rm 
inner join sys.database_principals r on rm.role_principal_id = r.principal_id
inner join sys.database_principals m on rm.member_principal_id = m.principal_id

一些附加信息:

  • 我在一个域中,但目前已断开连接。不过,我在连接时也遇到过这个问题。
  • 运行 Windows 8.1 64 位。

更新 2

如果我按照某些人的建议明确指定主体,我会收到此错误(以sa 执行):

SELECT IS_ROLEMEMBER('my_user', 'MYDOMAIN\UserX')

Msg 15404, Level 16, State 19, Line 1
Could not obtain information about Windows NT group/user 'MYDOMAIN\UserX',
error code 0x54b.

会不会是IS_ROLEMEMBER 遇到了同样的问题,但没有打印错误?

【问题讨论】:

  • IS_MEMBER() 呢?
  • 试过了。结果相同。
  • 它真的返回 0 还是 NULL?
  • 服务器登录名是否也可能是 Windows 用户组的名称?另外,当 SELECT IS_ROLEMEMBER('my_user', 'username') 时会产生什么结果?
  • 嗯。现在它起作用了。会不会这个函数为数据库所有者返回0?

标签: sql-server ssms


【解决方案1】:

我刚刚遇到了同样的问题...我发现有问题的用户也分配了服务器角色。当我删除除“public”之外的所有服务器角色时,is_rolemember 查询突然开始正确报告 1 而不是 0 ......我来回测试了几次以确认。

【讨论】:

  • 谢谢!这实际上可能是根本原因!
  • 我已经验证这是正确的答案。服务器角色,例如“sysadmin”,导致IS_ROLEMEMBER(错误地?)返回 0。对我来说看起来像一个错误。
  • 此页面上的其他答案之一 (stackoverflow.com/a/47093146/1786204) 涵盖了“为什么”(系统管理员将用户作为 dbo 呈现给数据库),因此它不完全是一个错误,但它很奇怪。
【解决方案2】:

尝试明确指定主体。

SELECT IS_ROLEMEMBER('my_user', 'SqlLogin')

我对此进行了测试,它返回了 1。

CREATE DATABASE TestDatabase;
GO

USE TestDatabase;
GO

CREATE ROLE TestRole AUTHORIZATION dbo;
GO

CREATE USER TestUser WITHOUT LOGIN;
GO

EXEC sp_addrolemember 'TestRole', 'TestUser';
GO

SELECT IS_ROLEMEMBER('TestRole', 'TestUser');
GO

【讨论】:

  • 如果TestUser 是数据库的所有者会怎样? TestRole 仍然返回 1 吗?
  • 我测试时仍然返回 1。
  • 这可能在 SQL Express 上有所不同吗?
  • 我不明白为什么会这样。从我所见,文档中没有任何内容暗示这一点。您是否尝试运行上述脚本?
  • 请看我的更新。当我使用域用户(离线)运行您的脚本时,我收到错误代码 0x54b。
【解决方案3】:

也有这个问题。原来我必须删除 sysadmin 服务器角色,然后它才起作用。

摘自:https://docs.microsoft.com/en-us/sql/t-sql/functions/is-member-transact-sql

sysadmin 固定服务器角色的成员以 dbo 用户身份进入每个数据库。检查 sysadmin 固定服务器角色成员的权限,检查 dbo 的权限,而不是原始登录名。由于 dbo 不能添加到数据库角色并且不存在于 Windows 组中,因此 dbo 将始终返回 0(如果角色不存在,则返回 NULL)。

【讨论】:

    猜你喜欢
    • 2017-02-20
    • 1970-01-01
    • 2021-08-11
    • 2011-01-10
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2018-05-21
    相关资源
    最近更新 更多