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?


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;

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;

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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.