Sha*_*ehr 6 security sql-server permissions sql-server-2016
我有一个用户ls_readonly应该拥有db_datareader多个数据库的权限。我以为我已经设置好了:
但是当我连接到服务器ls_readonly并尝试在对象资源管理器中打开数据库时,我收到一个错误:
数据库 wtest 不可访问。(对象浏览器)
我打开一个查询窗口master并尝试运行:
use wtest
Run Code Online (Sandbox Code Playgroud)
这回应:
Msg 916, Level 14, State 1, Line 1
The server principal "ls_readonly" is not able to access the database "wtest" under the current security context.
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
更新:这是一个线索。如果我ls_readonly作为用户从数据库的安全上下文中删除,那么我会转到服务器安全上下文下的用户,并在“用户映射”下授予对数据库的访问权限,然后它开始工作。
可能是该数据库最初是从另一台服务器恢复的,该服务器也有一个ls_readonly用户。我猜那么用户识别不是基于用户名?
sep*_*pic 16
可能是该数据库最初是从另一台服务器恢复的,该服务器也有一个 ls_readonly 用户。我猜那么用户识别不是基于用户名?
正常情况下,所有的登录都sid与对应的用户相同。这就是CREATE USER FROM LOGIN命令的意义:数据库主体是使用与sid相应登录名相同的(安全标识符)创建的。
这个用户sid现在存储在你的数据库中,当你backup/restore你的数据库时,sid 也被保留了。
想象一下,现在您有 2 台服务器,并且它们都已ls_readonly登录。为简单起见,在第一台服务器上ls_readonly有sid= 1,在第二台服务器上有sid= 2。您有数据库 MyDB,该登录名被映射到该数据库中。MyDB 在第一台服务器上存储sid= 1,在第二台服务器上存储sid= 2。
您在第一台服务器上备份 MyDB 数据库并在第二台服务器上恢复它。现在您的登录名sid= 2,在数据库 MyDB 中它是sid= 1。
您以身份登录ls_readonly并尝试访问 MyDB,服务器正在检查数据库中是否有 sid = 2,没有,因此服务器ls_readonly根本没有映射到 MyDB。
这可以通过做来解决
alter user ls_readonly with login = ls_readonly;
Run Code Online (Sandbox Code Playgroud)
这个命令只是ls_readonly用ls_readonly登录的 sid 更新用户的数据库的 sid 。保留所有权限。
如果通过删除用户重新创建用户,一旦删除用户,授予它的所有权限都将删除,您需要重新授予它们。
@sepupic盖得非常好一切,我会建议,但我想我会分享下面的脚本运行我只要我恢复从一个SQL Server实例的备份和还原到不同的一个数据库。在刚刚恢复的数据库中运行它。它基本上自动化了@sepupic 正在谈论的内容。(execute注释掉了)
SET NOCOUNT ON
DECLARE @cmd nVARCHAR(max) = ''
SELECT @Cmd = @cmd + 'ALTER USER ' + dp.NAME + ' WITH LOGIN = ' + dp.NAME + ';' + CHAR(10)
FROM sys.database_principals dp
LEFT JOIN master.sys.server_principals sp ON sp.NAME = dp.NAME
WHERE dp.type = 's'
AND dp.default_schema_name <> dp.NAME
AND sp.NAME IS NOT NULL
ORDER BY dp.NAME
PRINT @Cmd
--EXECUTE sp_executeSQL @CMD
Run Code Online (Sandbox Code Playgroud)
这听起来像是一个孤立的用户。孤立用户是指用户 SID 与登录 SID 不匹配的情况,而不是我们看到的友好名称(可能是由于从服务器中删除了登录名,或者从不同的服务器恢复了数据库)。您不需要删除用户并重新创建它,因为所有现有权限都将丢失(好吧,这只是角色,但假设您对其他对象具有单独的权限;存储过程和表等)。有一项功能允许您将用户重新映射到登录名(即使它是同名的)。
use db1
GO
alter user [user_name] with login = [login_name]
Run Code Online (Sandbox Code Playgroud)
所以它想:
use wtest
GO
alter user [ls_readonly] with login = [ls_readonly]
Run Code Online (Sandbox Code Playgroud)
请参阅此处了解 MS 文档中的更多详细信息