Batasi pembaruan pada kolom tertentu. Hanya izinkan prosedur tersimpan untuk memperbarui kolom tersebut

17

Saya memiliki kolom harga sensitif yang ingin saya perbarui hanya melalui prosedur tersimpan. Saya ingin semua kode atau upaya manual untuk mengubah nilai dalam kolom harga ini gagal jika tidak menggunakan prosedur tersimpan yang dirancang untuk memperbaruinya.

Saya sedang mempertimbangkan mengimplementasikan ini menggunakan trigger dan token table. Ide yang saya pertimbangkan adalah memiliki token table. prosedur yang tersimpan harus terlebih dahulu memasukkan nilai dalam tabel token. Kemudian perbarui kolom harga. Pemicu pembaruan akan memeriksa apakah token ada di tabel token untuk baris yang diperbarui. Jika ditemukan, itu akan berlanjut. jika token tidak ditemukan, itu akan melempar pengecualian dan membuat transaksi pembaruan gagal.

Apakah ada cara yang baik / lebih baik untuk menerapkan pembatasan ini?

Elias
sumber
1
Anda dapat menggunakan tampilan untuk keamanan berbasis kolom. Itu akan jauh lebih elegan daripada pemicu. Berikan pengguna izin pada tampilan tetapi tidak mendasari data.
Thomas Stringer
Itu poin yang bagus. Tetapi masalah tetap belum terpecahkan tanpa merusak banyak aplikasi yang menggunakan koneksi pooling.
Elias
Bisakah Anda menjelaskan bagaimana ini akan "memecah banyak aplikasi yang menggunakan pooling koneksi"?
Aaron Bertrand

Jawaban:

21

SQL Server memungkinkan izin tingkat kolom. Sebagai contoh:

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

sumber
Terima kasih Michal, tetapi solusi ini tidak berfungsi untuk saya karena, aplikasi saya adalah aplikasi web yang menggunakan pooling koneksi. Semua pengguna terhubung menggunakan String Koneksi SQL Server yang sama.
Elias
1
@ Elia saya tidak mengerti. String koneksi terhubung sebagai pengguna tertentu, bukan? Jadi gantikan SampleRoledengan pengguna itu ...
Aaron Bertrand
izin tingkat kolom adalah cara untuk pergi ke sini. Itu dan memastikan bahwa pengembang tahu bahwa membuat perubahan pada nilai-nilai melalui t-sql secara langsung akan menghancurkan sistem.
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
sumber
2

Jika semua pengguna Anda memiliki login yang sama (aduh, BTW) maka di sini ada pilihan lain

  • cabut hak pembaruan dari pengguna itu (atau peran, jika Anda melakukannya dengan cara itu).
  • Ubah proc yang tersimpan dengan klausa "eksekusi sebagai pemilik" di atasnya
  • maka proc yang disimpan akan dijalankan dengan hak-hak pengguna yang memiliki skema di mana ia berada (jika berada di dalamnya dbo, maka Anda sudah dilindungi).

Pengguna aplikasi reguler akan kekurangan hak pembaruan untuk tabel itu, sehingga mereka tidak akan dapat memperbaruinya dengan cara lain.

SqlRyan
sumber
Anda tidak perlu membuat pengguna baru untuk melakukan ini ...
Aaron Bertrand
@ aaronbertrand Anda benar - untuk itu, e reasonni berpikir Anda akan melakukan "eksekusi sebagai pembuat", tapi itu bukan apa-apa - Anda dapat melakukan "eksekusi sebagai pemilik" selama pengguna yang memiliki skema memiliki hak untuk perbarui tabel itu. Jika proc yang disimpan ada di dbo, maka Anda dilindungi. Saya akan memperbarui jawaban saya.
SqlRyan