我有 mssql2008 r2 sql server
问题:用户对表有一些列权限。他可以更新表的某些列(不是全部)。我们需要创建 UPDATE 语句,这样它就不会违反权限。最好没有动态查询。
MSSQL 服务器有这个能力吗?
我有 mssql2008 r2 sql server
问题:用户对表有一些列权限。他可以更新表的某些列(不是全部)。我们需要创建 UPDATE 语句,这样它就不会违反权限。最好没有动态查询。
MSSQL 服务器有这个能力吗?
没有动态 SQL(或应用程序或 API 层中的动态查询构造)?我不认为它会很漂亮。UPDATE 命令不知道用户可能对受影响的列拥有什么权限。它将向引擎提交查询并希望获得最好的结果。如果用户没有对所有列的权限,它将返回一个错误,而不是试图通过改变预期的语句来规避它。我认为继续更新实际上是一件非常糟糕的事情,即使并非所有预期的列都已更新。
综上所述,我想你可以做这样的事情,但它根本不会漂亮 - 事实上,如果你不依赖数据库主体,它会容易得多:
DECLARE
@dpid INT = DATABASE_PRINCIPAL_ID(),
@obj INT = OBJECT_ID('dbo.foo'),
@col SYSNAME = N'bar';
UPDATE dbo.foo SET bar = CASE
WHEN EXISTS -- check they've been granted UPDATE at column or table level:
(
SELECT 1
FROM sys.database_permissions AS dp
INNER JOIN sys.objects AS o
ON dp.major_id = o.[object_id]
LEFT OUTER JOIN sys.columns AS c
ON dp.minor_id = COALESCE(c.column_id, 0)
WHERE dp.grantee_principal_id = @dpid
AND o.[object_id] = @obj
AND (c.name = @col OR c.column_id IS NULL)
AND dp.[permission_name] = 'UPDATE'
AND dp.[state] = 'G' -- GRANT
)
AND NOT EXISTS -- since DENY trumps GRANT, make sure that doesn't also exist:
(
SELECT 1
FROM sys.database_permissions AS dp
INNER JOIN sys.objects AS o
ON dp.major_id = o.[object_id]
LEFT OUTER JOIN sys.columns AS c
ON dp.minor_id = COALESCE(c.column_id, 0)
WHERE dp.grantee_principal_id = @dpid
AND o.[object_id] = @obj
AND (c.name = @col OR c.column_id IS NULL)
AND dp.[permission_name] = 'UPDATE'
AND dp.[state] = 'D' -- DENY
)
THEN @bar ELSE bar END
-- WHERE...
;
这不完全是您所要求的;从技术上讲,它会更新列,但会将其设置为自身(例如,它仍将在触发器中指示为更新的列),但它会阻止将输入应用于表。除了对指定用户或角色的显式 GRANT UPDATE 或 DENY UPDATE 之外,我也没有检查以其他方式授予的权限——例如 GRANT ALL 或 AD 组成员身份继承的权限,这会使情况复杂化。当然,如果您有多个列要检查,那么管理它根本不会很有趣。
您可能希望在 WHEN 子句中添加其他条件,例如,为了避免检查 dbo (who ) 或您想要明确绕过检查的用户,您可以:
CASE
WHEN DATABASE_PRINCIPAL_ID() = 1 THEN @bar
WHEN SUSER_SNAME = 'some_user' THEN @bar
WHEN (...stuff from above...)
ELSE bar
END
-- WHERE...
;