我们有一个 SQL Server 2016,上面有 20 个不同的数据库,供公司内的不同应用程序和不同团队使用。Active Directory 中有用户组,这些用户组将负责某些项目的员工组合在一起。问题是一名员工可以同时成为多个团队的成员。同一个人可以属于多个不同的 AD 组。
一位用户抱怨他无法访问某个数据库。当他尝试刷新查询该数据库的 Power BI 报告时,他收到一条错误消息“我们无法使用提供的凭据进行身份验证”。
下面是一张简化的图片。一台服务器有两个数据库:DB1
和。SQL Server 中DB2
有两个 AD 组App_Excel_Reporter
和以及两个相应的登录名:DB2_User
CREATE LOGIN [LegacyDomain\App_Excel_Reporter] FROM WINDOWS WITH DEFAULT_DATABASE=[master]
CREATE LOGIN [Domain\DB2_User] FROM WINDOWS WITH DEFAULT_DATABASE=[master]
不确定这是否重要,但该服务器是主公司收购的另一家公司的旧服务器。因此,这台 SQL Server 计算机位于域中LegacyDomain
。
两个 AD 组LegacyDomain\App_Excel_Reporter
都有Domain\DB2_User
自己的用户集,但一个用户同时Jack.Universal
属于这两个 AD 组。
属于 的用户App_Excel_Reporter
应该有权访问DB1
。 属于 的用户DB2_User
应该有权访问DB2
。
其中DB1
有一个用户映射到相应的登录名:
USE [DB1]
GO
CREATE USER [LegacyDomain\App_Excel_Reporter] FOR LOGIN [LegacyDomain\App_Excel_Reporter] WITH DEFAULT_SCHEMA=[dbo]
GO
其中DB2
有一个用户映射到相应的登录名:
USE [DB2]
GO
CREATE USER [Domain\DB2_User] FOR LOGIN [Domain\DB2_User] WITH DEFAULT_SCHEMA=[dbo]
GO
当用户Jack.Universal
尝试刷新 Power BI 时,他会在笔记本电脑上登录 Windows,并且Domain\Jack.Universal
我在 SQL Server 日志中看到具有相同时间戳的这些消息:
Login succeeded for user 'Domain\Jack.Universal'. Connection made using Windows authentication, [CLIENT: <ip address>]
Error: 18456, Severity: 14, State: 38.
Login failed for user 'Domain\Jack.Universal'. Reason: Failed to open the explicitly specified database 'DB2'. [CLIENT: <ip address>]
当我跑步时
xp_logininfo 'Domain\Jack.Universal', @option = 'all'
表明
+-----------------------+------+-----------+-----------------------+---------------------------------+
| account name | type | privilege | mapped login name | permission path |
+-----------------------+------+-----------+-----------------------+---------------------------------+
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | LegacyDomain\App_Excel_Reporter |
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | Domain\DB2_User |
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | Domain\DB3_User |
+-----------------------+------+-----------+-----------------------+---------------------------------+
(是的,有两个以上的数据库,并且该用户属于三个 AD 组)
如果我跑
xp_logininfo 'Domain\Jack.Universal'
如果没有选项“all”,则只返回第一行:
+-----------------------+------+-----------+-----------------------+---------------------------------+
| account name | type | privilege | mapped login name | permission path |
+-----------------------+------+-----------+-----------------------+---------------------------------+
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | LegacyDomain\App_Excel_Reporter |
+-----------------------+------+-----------+-----------------------+---------------------------------+
Domain\Jack.Universal
因此,当 Windows 用户登录到 SQL Server 时,SQL Server似乎会选择登录LegacyDomain\App_Excel_Reporter
来让该用户进入,但是当它尝试访问数据库时,DB2
此尝试会失败,因为登录LegacyDomain\App_Excel_Reporter
仅映射到中的用户DB1
。
“明确指定的数据库”一定是由于 Power BI 的连接字符串明确指定了DB2
。
我们如何配置,以便属于两个 AD 组的用户能够访问两个数据库?仅属于一个 AD 组的用户只能访问相应的数据库。
我不是域管理员,但我可以向他们询问任何需要的信息。公司没有 DBA,我只是一名对 SQL Server 略知一二的程序员。
我挖得更深了一点。当我跑
EXEC xp_logininfo 'Domain\DB2_User', @option = 'members'
我获得了该组中的用户列表:
+-----------------------+------+-----------+-----------------------+-----------------+
| account name | type | privilege | mapped login name | permission path |
+-----------------------+------+-----------+-----------------------+-----------------+
| Domain\user1 | user | user | Domain\user1 | Domain\DB2_User |
| Domain\user2 | user | user | Domain\user2 | Domain\DB2_User |
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | Domain\DB2_User |
+-----------------------+------+-----------+-----------------------+-----------------+
并且用户也Domain
正如预期的那样。
当我跑步时
EXEC xp_logininfo 'LegacyDomain\App_Excel_Reporter', @option = 'members'
我明白了:
+-----------------------------+------+-----------+-----------------------------+---------------------------------+
| account name | type | privilege | mapped login name | permission path |
+-----------------------------+------+-----------+-----------------------------+---------------------------------+
| LegacyDomain\user3 | user | user | LegacyDomain\user3 | LegacyDomain\App_Excel_Reporter |
| LegacyDomain\user4 | user | user | LegacyDomain\user4 | LegacyDomain\App_Excel_Reporter |
| LegacyDomain\Jack.Universal | user | user | LegacyDomain\Jack.Universal | LegacyDomain\App_Excel_Reporter |
+-----------------------------+------+-----------+-----------------------------+---------------------------------+
这里权限路径在LegacyDomain
,账户名也在LegacyDomain
,但是上面的结果中xp_logininfo 'Domain\Jack.Universal'
账户名在Domain
,但是权限路径在LegacyDomain
。
再次:
EXEC xp_logininfo 'Domain\Jack.Universal', @option = 'all'
+-----------------------+------+-----------+-----------------------+---------------------------------+
| account name | type | privilege | mapped login name | permission path |
+-----------------------+------+-----------+-----------------------+---------------------------------+
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | LegacyDomain\App_Excel_Reporter |
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | Domain\DB2_User |
| Domain\Jack.Universal | user | user | Domain\Jack.Universal | Domain\DB3_User |
+-----------------------+------+-----------+-----------------------+---------------------------------+
EXEC xp_logininfo 'LegacyDomain\Jack.Universal', @option = 'all'
+-----------------------------+------+-----------+-----------------------------+---------------------------------+
| account name | type | privilege | mapped login name | permission path |
+-----------------------------+------+-----------+-----------------------------+---------------------------------+
| LegacyDomain\Jack.Universal | user | user | LegacyDomain\Jack.Universal | LegacyDomain\App_Excel_Reporter |
+-----------------------------+------+-----------+-----------------------------+---------------------------------+
Active Directory 中一定存在一些神奇的功能,可以将用户从旧域映射到主域。
如果您将 AD 用户添加或删除到 AD 组,并且想要在不让用户注销的情况下立即强制执行这些更改,则用户需要在
cmd
或 Powershell 窗口中执行以下命令如果这是你添加/删除的机器,那么你需要
这样做的目的是清除 Kerberos 票证缓存,因此下次需要 Kerberos 票证时,将联系域控制器获取新的 TGT 票证,新票证包含更新后的组列表。否则,缓存将保留票证,直到到期(通常为 10 小时)或注销。
要确认更改,请执行
据我所知,如果您尝试使用 Active Directory 中的通用组访问 SQL Server,您会注意到这些组的成员用户无法访问 SQL Server 实例。造成这种情况的原因与 Active Directory 的关系比与 SQL Server 的关系更大。
Active Directory 中的普通组会被缓存,因此身份验证请求可以返回用户所属的组作为 Windows 令牌的一部分。但是,通用组不包含在 Windows 令牌中,因为用户所属的通用组可能不在处理请求的同一域中。
因为当 SQL Server 去查看用户是否具有访问权限时,通用组不在身份验证令牌中,所以令牌显示用户没有访问权限。修复这个问题非常简单,使用与通用组不同的 Windows 域组类型。
我不知道启用通用组缓存是否可以解决问题: https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/planning-global-catalog-server-placement#enabling-universal-group-membership-caching