Restrinja a atualização em determinadas colunas. Permitir apenas que o procedimento armazenado atualize essas colunas

17

Tenho colunas de preços confidenciais que gostaria de atualizar apenas por meio de um procedimento armazenado. Gostaria que todo o código ou tentativas manuais de alterar os valores nessas colunas de preços falhasse se não estivesse usando os procedimentos armazenados projetados para atualizá-lo.

Estou pensando em implementar isso usando gatilhos e uma tabela de token. A idéia que estou pensando é ter uma tabela de token. os procedimentos armazenados precisarão primeiro inserir valores na tabela de token. Atualize as colunas de preço. O gatilho de atualização verificará se o token existe na tabela de tokens para a linha atualizada. Se encontrado, continuaria. se o token não for encontrado, lançará uma exceção e fará com que a transação de atualização falhe.

Existe uma maneira boa / melhor de implementar essa restrição?

Elias
fonte
1
Você pode usar uma exibição para segurança baseada em coluna. Isso será muito mais elegante do que um gatilho. Conceda aos usuários permissão na exibição, mas não nos dados subjacentes.
22612 Thomas Stringer
Essa é uma boa opinião. Mas o problema permanece sem solução sem interromper muitos aplicativos que estão usando o pool de conexões.
Elias
Você pode explicar como isso estará "quebrando muitos aplicativos que estão usando o pool de conexões"?
Aaron Bertrand

Respostas:

21

O SQL Server permite permissões no nível da coluna. Apenas por exemplo:

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

fonte
Obrigado Michal, mas esta solução não funcionará para mim porque, meu aplicativo é um aplicativo da Web que está usando o pool de conexões. Todos os usuários se conectam usando a mesma seqüência de conexão do SQL Server.
Elias
1
@ Elias eu não entendo. A cadeia de conexão se conecta como um usuário específico, certo? Então substitua SampleRolepor esse usuário ...
Aaron Bertrand
as permissões no nível da coluna são o caminho a seguir aqui. Isso e garantir que os desenvolvedores saibam que fazer alterações nos valores via t-sql diretamente destruirá o sistema.
Mrdenny 23/09/12
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;
Aaron Bertrand
fonte
2

Se todos os seus usuários tiverem o mesmo login (ai, BTW), aqui está outra opção

  • revogar os direitos de atualização desse usuário (ou função, se você estiver fazendo dessa maneira).
  • Altere o processo armazenado com a cláusula "executar como proprietário"
  • o processo armazenado será executado com os direitos do usuário que possui o esquema no qual ele reside (se dboestiver, então você já está coberto).

Os usuários regulares do aplicativo não terão direitos de atualização para essa tabela, portanto, não poderão atualizá-la de outra maneira.

SqlRyan
fonte
Você não precisa criar um novo usuário para fazer isso ...
Aaron Bertrand
@aaronbertrand, você está certo - por isso, e reasonni estava pensando em fazer "executar como criador", mas isso não é uma coisa - você pode executar "executar como proprietário" desde que o usuário proprietário do esquema tenha direitos a atualize essa tabela. Se o processo armazenado estiver no dbo, você estará coberto. Vou atualizar minha resposta.
SqlRyan