Restreindre la mise à jour sur certaines colonnes. Autoriser uniquement la procédure stockée à mettre à jour ces colonnes

17

J'ai des colonnes de prix sensibles que j'aimerais mettre à jour uniquement via une procédure stockée. J'aimerais que toutes les tentatives de code ou manuelles pour modifier les valeurs de ces colonnes de prix échouent si elles n'utilisent pas les procédures stockées conçues pour le mettre à jour.

J'envisage de l'implémenter à l'aide de déclencheurs et d'une table de jetons. L'idée que j'envisage est d'avoir une table de jetons. les procédures stockées devront d'abord insérer des valeurs dans la table des jetons. Mettez ensuite à jour les colonnes de prix. Le déclencheur de mise à jour vérifiera si le jeton existe dans la table des jetons pour la ligne mise à jour. S'il était trouvé, il continuerait. si le jeton n'est pas trouvé, il lèvera une exception et fera échouer la transaction de mise à jour.

Existe-t-il un bon / meilleur moyen de mettre en œuvre cette restriction?

Elias
la source
1
Vous pouvez utiliser une vue pour la sécurité basée sur les colonnes. Ce sera beaucoup plus élégant qu'un déclencheur. Accordez aux utilisateurs l'autorisation sur la vue mais pas sur les données sous-jacentes.
Thomas Stringer
C'est un bon point. Mais le problème reste non résolu sans interrompre un grand nombre d'applications qui utilisent le pool de connexions.
Elias
Pouvez-vous expliquer comment cela va "casser un grand nombre d'applications qui utilisent le pool de connexions"?
Aaron Bertrand

Réponses:

21

SQL Server autorise les autorisations au niveau des colonnes. Par exemple:

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

la source
Merci Michal, mais cette solution ne fonctionnera pas pour moi car, mon application est une application Web qui utilise le pool de connexions. Tous les utilisateurs se connectent à l'aide de la même chaîne de connexion SQL Server.
Elias
1
@Elias je ne comprends pas. La chaîne de connexion se connecte en tant qu'utilisateur spécifique, non? Alors remplacez SampleRolepar cet utilisateur ...
Aaron Bertrand
les autorisations au niveau des colonnes sont la voie à suivre ici. Cela et garantir que les développeurs savent que la modification directe des valeurs via t-sql détruira le système.
mrdenny
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
la source
2

Si tous vos utilisateurs ont la même connexion (ouch, BTW) alors voici une autre option

  • révoquer les droits de mise à jour de cet utilisateur (ou rôle, si vous le faites de cette façon).
  • Modifiez le proc stocké avec la clause "exécuter en tant que propriétaire"
  • alors le proc stocké s'exécutera avec les droits de l'utilisateur qui possède le schéma dans lequel il réside (si c'est le cas dbo, alors vous êtes déjà couvert).

Les utilisateurs réguliers de l'application n'auront pas de droits de mise à jour sur cette table, ils ne pourront donc pas la mettre à jour d'une autre manière.

SqlRyan
la source
Vous n'avez pas besoin de créer un nouvel utilisateur pour ce faire ...
Aaron Bertrand
@aaronbertrand vous avez raison - pour cette raison, e reasonni pensait que vous feriez "exécuter en tant que créateur", mais ce n'est pas une chose - vous pouvez faire "exécuter en tant que propriétaire" tant que l'utilisateur propriétaire du schéma avait le droit de mettre à jour cette table. Si le proc stocké est en dbo, alors vous êtes couvert. Je mettrai à jour ma réponse.
SqlRyan