限制对某些列的更新。只允许存储过程更新这些列


17

我有一些敏感的价格列,希望仅通过存储过程进行更新。如果不使用用于更新价格的存储过程,我希望所有代码或手动尝试更改这些价格列中的值都会失败。

我正在考虑使用触发器和令牌表来实现。我正在考虑的想法是有一个令牌表。存储过程将必须首先在令牌表中插入值。然后更新价格列。更新触发器将检查令牌表中是否存在已更新行的令牌。如果找到,它将继续。如果找不到令牌,它将引发异常并使更新事务失败。

有没有一种更好/更好的方法来实施此限制?


1
您可以将视图用于基于列的安全性。这比触发器要优雅得多。向用户授予视图权限,但不授予基础数据权限。
Thomas Stringer 2012年

这是一个好点。但是,在不破坏使用连接池的许多应用程序的情况下,问题仍然没有得到解决。
埃里亚斯2012年

您能解释一下这将“破坏使用连接池的许多应用程序”吗?
亚伦·伯特兰

Answers:


21

SQL Server允许列级权限。仅举例来说:

GRANT UPDATE ON dbo.Person (FirstName, LastName) TO SampleRole;
DENY UPDATE ON dbo.Person (Age, Salary) TO SampleRole;

感谢Michal,但是该解决方案对我不起作用,因为我的应用程序是使用连接池的Web应用程序。所有用户使用相同的SQL Server连接字符串进行连接。
埃里亚斯2012年

1
@Elias我不明白。连接字符串以特定用户身份连接,对吗?因此,SampleRole用该用户替换...
亚伦·贝特朗

列级权限是此处的解决方法。这并确保开发人员知道直接通过t-sql更改值将破坏系统。
mrdenny 2012年

6
-- prevent your web app user from updating that column directly:

DENY UPDATE ON dbo.YourTable(Price) TO WebApplicationUserName;
GO

-- create a stored procedure while logged in as sysadmin:

CREATE PROCEDURE dbo.UpdateYourTable
  @ProductID INT,
  @Price DECIMAL(10,2)
WITH EXECUTE AS OWNER
AS
BEGIN
  SET NOCOUNT ON;

  UPDATE dbo.YourTable 
    SET Price = @Price
    WHERE ProductID = @ProductID;
END
GO

-- grant explicit access only to that stored procedure to the web app user:

GRANT EXEC ON dbo.UpdateYourTable TO WebApplicationUserName;

2

如果您的所有用户都具有相同的登录名(ouch,BTW),那么这是另一种选择

  • 撤消该用户的更新权限(或角色,如果您这样做的话)。
  • 使用“以所有者身份执行”子句更改存储的过程
  • 那么存储的proc将以拥有它所驻留的架构的用户的权限运行(如果位于dbo,则您已被覆盖)。

常规应用程序用户将缺少对该表的更新权限,因此他们将无法以其他任何方式对其进行更新。


您无需创建新用户即可执行此操作
亚伦·贝特朗

@aaronbertrand,您是对的-出于这个原因,理由是您认为您应该“以创建者身份执行”,但这不是问题-只要拥有架构的用户有权执行“以所有者身份执行”更新该表。如果存储的proc在dbo中,则可以满足要求。我将更新我的答案。
SqlRyan 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.