Ogranicz aktualizację do niektórych kolumn. Zezwalaj tylko na procedurę składowaną, aby zaktualizować te kolumny

17

Mam wrażliwe kolumny cen, które chciałbym zaktualizować tylko za pomocą procedury składowanej. Chciałbym, aby wszystkie próby zmiany kodu w tych kolumnach cenowych lub ręczne próby zakończyły się niepowodzeniem, jeśli nie używa procedur przechowywanych zaprojektowanych do jego aktualizacji.

Rozważam wdrożenie tego przy użyciu wyzwalaczy i tabeli tokenów. Rozważam pomysł posiadania tabeli żetonów. procedury składowane będą musiały najpierw wstawić wartości do tabeli tokenów. Następnie zaktualizuj kolumny cen. Wyzwalacz aktualizacji sprawdzi, czy token istnieje w tabeli tokenów dla zaktualizowanego wiersza. Jeśli zostanie znaleziony, będzie kontynuowany. jeśli token nie zostanie znaleziony, wygeneruje wyjątek i spowoduje niepowodzenie transakcji aktualizacji.

Czy istnieje dobry / lepszy sposób na wdrożenie tego ograniczenia?

Elias
źródło
1
Możesz użyć widoku dla bezpieczeństwa opartego na kolumnach. To będzie o wiele bardziej eleganckie niż spust. Zezwól użytkownikom na widok, ale nie podstawowe dane.
Thomas Stringer
To dobra uwaga. Ale problem pozostaje nierozwiązany bez zerwania wielu aplikacji korzystających z puli połączeń.
Elias
Czy możesz wyjaśnić, jak to będzie „zepsuć wiele aplikacji korzystających z puli połączeń”?
Aaron Bertrand

Odpowiedzi:

21

SQL Server pozwala na uprawnienia na poziomie kolumny. Na przykład:

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

źródło
Dzięki Michał, ale to rozwiązanie nie będzie dla mnie działać, ponieważ moja aplikacja jest aplikacją internetową, która korzysta z puli połączeń. Wszyscy użytkownicy łączą się przy użyciu tego samego ciągu połączenia programu SQL Server.
Elias
1
@Elias Nie rozumiem. Ciąg połączenia łączy się jako określony użytkownik, prawda? Zastąp więc SampleRoletego użytkownika ...
Aaron Bertrand
tutaj można przejść na poziomie uprawnień na poziomie kolumny. To i upewnienie się, że programiści wiedzą, że wprowadzanie zmian wartości bezpośrednio przez t-sql zniszczy system.
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
źródło
2

Jeśli wszyscy użytkownicy mają ten sam login (ouch, BTW), oto inna opcja

  • odwołać prawa do aktualizacji od tego użytkownika (lub roli, jeśli robisz to w ten sposób).
  • Zmień zapisany proc z klauzulą ​​„wykonaj jako właściciel”
  • wówczas przechowywany proc będzie działał z prawami użytkownika, który jest właścicielem schematu, w którym się on znajduje (jeśli jest w dbo, to jesteś już objęty).

Zwykłym użytkownikom aplikacji brakuje uprawnień do aktualizacji tej tabeli, więc nie będą mogli jej zaktualizować w żaden inny sposób.

SqlRyan
źródło
Nie musisz tworzyć nowego użytkownika, aby to zrobić ...
Aaron Bertrand
@ aaronbertrand masz rację - bo więc powód myślał, że zrobisz „wykonaj jako twórca”, ale to nie jest rzecz - możesz wykonać „wykonać jako właściciel”, o ile użytkownik będący właścicielem schematu miał prawa do zaktualizuj tę tabelę. Jeśli przechowywany proc jest w dbo, to jesteś objęty ubezpieczeniem. Zaktualizuję moją odpowiedź.
SqlRyan