4

除了 MS SQL Server 中的任何东西之外,我一直讨厌的一件事是安全性的工作方式。如果你觉得服务器很有趣,安全上下文会不断切换,而且通常很难(无论如何对我来说)预测或调试。

不过,在今天处理一个问题时,“我希望我可以在我的代码中添加一行,以显示 SQL Server 在此代码运行时使用的安全上下文。” 这样的命令存在吗?例如,SELECT security_context()

更清楚一点......如果我在一个存储过程中并且因此受制于 SP 所有者的安全上下文,那么我希望看到这一点。如果我在 sp_executesql 调用的代码中,并且它导致安全性位于 SQL Server 服务帐户的上下文中,那么我希望看到这一点。

至少那时我可能能够弄清楚为什么 SQL Server 认为我不应该访问某些东西。

谢谢!


例子

-- Set up
CREATE USER Test_User WITHOUT LOGIN
CREATE TABLE Test_Security_Context (my_id INT)
INSERT INTO Test_Security_Context VALUES (1)
DENY SELECT ON Test_Security_Context TO Test_User
GO
CREATE PROCEDURE Test_Security_Context_SP
AS
  SELECT SUSER_SNAME()
  SELECT * FROM Test_Security_Context  -- This will return ok
  EXEC('SELECT SUSER_SNAME(); SELECT * FROM Test_Security_Context')  -- SUSER_SNAME() will match above but select fails
GO
GRANT EXECUTE ON Test_Security_Context_SP TO Test_User
GO

-- Switch to the new user
SETUSER 'Test_User'
GO

-- Do the test
EXEC Test_Security_Context_SP
GO

-- Clean up
SETUSER
DROP PROCEDURE Test_Security_Context_SP
DROP TABLE Test_Security_Context
DROP USER Test_User
GO
4

3 回答 3

4

是的,考虑到 EXECUTE AS 或代码签名等所有细节,有这样一对表示您当前安全上下文的视图:

您获得的每一次访问最终都来自这些结果的返回中的一行。请注意,某些访问权限是硬编码的角色成员身份隐含的(例如 db_datareader 数据库角色或 sysadmin 服务器角色)。

除此之外:

  • 所有权链接与安全上下文无关:您不在 SP 所有者的“上下文”下。所有权链接简单地指出,对于与当前对象(SP、视图)拥有相同所有者的对象,会跳过访问检查。
  • sp_executesql不会以任何方式更改安全上下文
于 2010-08-02T23:07:48.367 回答
2

不确定这是否是您所说的安全上下文,但您可以检索与您的会话关联的用户,例如:

select SYSTEM_USER

这适用于 SQL Server 登录或 WINdows 登录。它甚至可以在带有execute as owner. 例如,

create procedure dbo.Test
with execute as owner
as
select SYSTEM_USER
go
exec dbo.Test
select SYSTEM_USER

印刷:

sa
MyMachine\MyName

如果您正在寻找 SQL Server 用来代表您执行操作的 Windows 帐户,您可以尝试whoami从以下命令运行:

EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE

EXEC master..xp_cmdshell 'whoami'

对我来说,返回nt authority\network service.

于 2010-08-02T21:02:09.787 回答
1

我想你想用它CURRENT_USER来查看当前的安全上下文。这是一个例子:

SELECT CURRENT_USER AS 'Current User Name';
GO
EXECUTE AS LOGIN = 'junk'
GO
SELECT CURRENT_USER AS 'Current User Name';
GO
REVERT
SELECT CURRENT_USER AS 'Current User Name';
GO

带输出(注意:我是我的 SQL Server 的管理员)

Current User Name
------------------
dbo

(1 row(s) affected)

Current User Name
------------------
Junk

(1 row(s) affected)

Current User Name
------------------
dbo

(1 row(s) affected)
于 2010-08-02T22:12:10.297 回答