tsi*_*lar 5 sql-server active-directory sql-server-2008
当存在歧义时,SQL Server如何处理登录,例如,Windows用户帐户和包含此用户的AD组都存在登录?
我们在SQL Server 2008中使用Active Directory中的Windows用户和该AD中的组的权限存在一些问题.我将尝试用一个例子来解释.
想象一下DOMAIN\myUser属于AD组的Windows域用户DOMAIN\SomeGroup.
在SQL Server中,我有2个数据库SomeAppDb和PublicDb.
目标是作为成员的所有用户都DOMAIN\SomeGroup应该能够访问PublicDb,但只能DOMAIN\myUser访问SomeAppDb.
最初,在SQL Server中,在DOMAIN\SomeGroup实例上创建了一个Windows登录(映射到AD组),并且在PublicDb具有适当角色成员资格的数据库中创建了一个用户,并且该用户运行良好,来自组的用户SomeGroup可以访问他们所需的数据PublicDb.
为了满足新应用程序的需求,我们希望为用户提供db SomeAppDb的显式访问权限DOMAIN\myUser,同时仍允许访问PublicDb.因此,我们在SQL Server中创建了一个Windows登录名DOMAIN\myUser,并在数据库中创建了一个User,并SomeAppDb在2之间进行了映射.
从那时起,myUser可以SomeAppDb按预期访问,但无法再访问PublicDb,我们遇到如下错误:
Cannot open database "PublicDb" requested by the login. The login failed.
Login failed for user 'DOMAIN\myUser'
Run Code Online (Sandbox Code Playgroud)
我的直觉告诉我,当用户访问SQL Server实例时,SQL Server会看到与Windows用户匹配的登录,并忽略用户所属组的现有登录.
一种方法是明确地为用户myUser在db PublicDb上添加访问权限,但我宁愿避免使用该解决方案,因为每次我们想要访问新用户时它都会强制更新PublicDb,这正是我们最初想要避免的... (我们这样做是临时修复,希望找到更好的选择).
还有其他人遇到过这个问题吗?有更好的方法吗?
提前致谢
我的直觉告诉我,当用户访问SQL Server实例时,SQL Server会看到与Windows用户匹配的登录,并忽略用户所属组的现有登录.
这种直觉是不正确的.这是一件好事,因为您希望安全设置工作的方式是它应该工作的方式; 权限是附加的.我刚刚复制了您的设置,并且为Windows登录创建了登录对于仅分配给基于Windows组的登录的权限(即特定的数据库访问)没有任何不利影响.我甚至可以将基于Windows登录的登录的默认数据库设置为只能通过与基于Windows组的登录相关的映射访问的数据库.是的,我的测试Login只是public服务器和数据库角色的成员,我确实验证了任何未显式映射到基于Windows组的登录或基于Windows登录的登录的数据库根本无法访问.
所以,我很确定在所提到的内容或其他配置之外的某些内容正在改变这种情况.但首先,我们可能应该清楚确切的问题.问题的描述说明:
从那时起,myUser可以按预期访问SomeAppDb,但无法再访问PublicDb
这必须意味着myUser能够登录.但是,用户以某种方式无法通过USE [PublicDb]?更改为PublicDb ?或者我们在谈论其他事情?也许是确切错误消息暗示的其他内容:
无法打开登录请求的数据库"PublicDb".登录失败.用户'DOMAIN\myUser'登录失败
如果myUser已登录并只是更改数据库或执行跨数据库查询,则不会出现"登录失败"错误消息.这使我怀疑默认数据库(或连接字符串中指定的数据库)是SomeAppDb如上所述,那里没有问题.但是它必须是指定"PublicDb"的连接字符串才有问题.如果是这样,那个相同的连接字符串,复制和粘贴(不重新输入)是否适合其他人工作?也许在连接字符串中有一个typeo,甚至是一个隐藏的字符,指定"PublicDb"?我能够重现该错误的唯一方法是通过SQLCMD连接,同时指定一个数据库:
-d "[PublicDb]")如果不是连接字符串问题,请检查以下内容:
当DOMAIN\myUser登录到SQL Server中,DOMAIN\myUser应运行以下命令:
-- http://msdn.microsoft.com/en-us/library/ms186271.aspx (IS_MEMBER)
SELECT IS_MEMBER(N'DOMAIN\SomeGroup');
Run Code Online (Sandbox Code Playgroud)
如果该登录确实在该组中,那么它将返回一个1.如果没有,则:
0 表示登录是Windows登录但不在该组中,因此它已从组中删除,或NULL意味着这不是Windows登录(似乎不太可能,因为SQL Server中的登录名具有\不是SQL Server登录的有效字符)当DOMAIN\myUser登录到SQL Server:
DOMAIN\myUser用户所在的临时修订PublicDb.DOMAIN\myUser 应该运行以下内容:
SELECT HAS_DBACCESS(sd.[name]) AS [HasAccess], *
FROM sys.databases sd
ORDER BY 1 DESC, [name] ASC;
Run Code Online (Sandbox Code Playgroud)
是否PublicDb显示在列表中?
运行以下查询:
SELECT *
FROM sys.server_principals
WHERE [name] IN ('DOMAIN\myUser', 'DOMAIN\SomeGroup');
Run Code Online (Sandbox Code Playgroud)
检查以下字段:sid,type_desc,和default_database_name.确保"默认数据库"确实是一个数据库.可能是您最初添加Login for时设置的值不正确DOMAIN\myUser.如果没有别的,也许尝试将其设置[master]为查看是否可以解决错误.如果可行,请将其重新设置为[PublicDb].
让"myUser"登录到Windows,转到命令提示符,然后运行:
SQLCMD -E -Q"SELECT DB_NAME(), USER; USE [PublicDb]; SELECT DB_NAME(), USER;"
Run Code Online (Sandbox Code Playgroud)
返回的第一行应该是SomeAppDb DOMAIN\myUser.然后是关于切换数据库上下文的消息.然后他们应该看到PublicDb DOMAIN\myUser.
DOMAIN\myUser超出"用户是在数据库SomeAppDb中创建,并在2之间的映射" 时,做了任何事情.例如拒绝任何服务器级或数据库级权限?让"myUser"登录到Windows,转到命令提示符,然后运行:
SQLCMD -E -Q"SELECT DB_NAME(), USER;" -d"PublicDb"
Run Code Online (Sandbox Code Playgroud)
他们应该返回一行PublicDb DOMAIN\myUser.如果是,那么这绝对不是"登录"问题.
PublicDbSomeAppDb为该登录创建用户(无额外选项)(例如CREATE USER [DOMAIN\myUser] FOR LOGIN [DOMAIN\myUser])DOMAIN\myUser用户SomeAppDb,然后摆脱DOMAIN\myUser登录.如果其中一个确实导致了这个错误,那么此时DOMAIN\myUser应该能够PublicDb再次访问.PS大多数处理相同错误的相关帖子最终要么创建要使用的SQL Server登录,要么将基于Windows的登录添加到"db_owner"角色.我认为这两种解决方案都是解决方案,计算机的行为并不是随意的,所以我们只需找到原因.