Ini mudah dilakukan dengan cara yang sangat aman menggunakan Modul Signing. Ini akan serupa dengan dua jawaban saya berikut, juga di sini di DBA.StackExchange, yang memberikan contoh melakukan hal ini:
Keamanan prosedur tersimpan dengan eksekusi sebagai, kueri basis data lintas, dan penandatanganan modul
Izin di pemicu saat menggunakan sertifikat lintas basis data
Perbedaan untuk pertanyaan khusus ini adalah bahwa ia berkaitan dengan Tampilan, dan Tampilan tidak dapat ditandatangani. Jadi, Anda perlu mengubah Tampilan menjadi Fungsi Table-Valued (TVF) multi-pernyataan karena fungsi tersebut dapat ditandatangani dan dapat diakses seperti halnya Tampilan (well, for SELECT
access).
Contoh kode berikut menunjukkan melakukan persis apa yang diminta dalam pertanyaan di mana Login / Pengguna "RestrictedUser" hanya memiliki akses ke "DatabaseA" dan belum bisa mendapatkan data dari "DatabaseB". Ini hanya berfungsi dengan memilih dari TVF yang satu ini , dan hanya karena itu ditandatangani.
Untuk mendapatkan akses lintas-basis data jenis ini saat masih menggunakan Tampilan, dan tidak memberikan izin tambahan kepada Pengguna, akan membutuhkan Pengaktifan Kepemilikan Lintas-Database. Itu jauh lebih tidak aman karena itu sepenuhnya terbuka untuk semua objek antara kedua Database (tidak dapat dibatasi untuk objek dan / atau Pengguna tertentu). Penandatanganan Modul memungkinkan TVF yang satu ini memiliki akses lintas-DB (Pengguna tidak memiliki izin, TVF memilikinya), dan Pengguna yang tidak dapat SELECT
dari TVF tidak memiliki akses ke "DatabaseB" sama sekali.
USE [master];
CREATE LOGIN [RestrictedUser] WITH PASSWORD = 'No way? Yes way!';
GO
---
USE [DatabaseA];
CREATE USER [RestrictedUser] FOR LOGIN [RestrictedUser];
GO
CREATE FUNCTION dbo.DataFromOtherDB()
RETURNS @Results TABLE ([SomeValue] INT)
AS
BEGIN
INSERT INTO @Results ([SomeValue])
SELECT [SomeValue]
FROM DatabaseB.dbo.LotsOfValues;
RETURN;
END;
GO
GRANT SELECT ON dbo.[DataFromOtherDB] TO [RestrictedUser];
GO
---
USE [DatabaseB];
CREATE TABLE dbo.[LotsOfValues]
(
[LotsOfValuesID] INT IDENTITY(1, 1) NOT NULL
CONSTRAINT [PK_LotsOfValues] PRIMARY KEY,
[SomeValue] INT
);
INSERT INTO dbo.[LotsOfValues] VALUES
(1), (10), (100), (1000);
GO
---
USE [DatabaseA];
SELECT * FROM dbo.[DataFromOtherDB]();
EXECUTE AS LOGIN = 'RestrictedUser';
SELECT * FROM dbo.[DataFromOtherDB]();
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/
REVERT;
Semua langkah di atas menciptakan kembali situasi saat ini: Pengguna memiliki akses ke DatabaseA, memiliki izin untuk berinteraksi dengan objek di DatabaseA, tetapi mendapat kesalahan karena objek di DatabaseA mengakses sesuatu di DatabaseB di mana Pengguna tidak memiliki akses.
Langkah-langkah di bawah ini mengatur Modul Singing. Ini melakukan hal berikut:
- membuat Sertifikat di DatabaseA
- Menandatangani TVF dengan Sertifikat
- Menyalin Sertifikat (tanpa Kunci Pribadi) ke Basis Data B
- Menciptakan Pengguna di DatabaseB dari Sertifikat
- Memberikan
SELECT
izin ke Tabel di DatabaseB untuk Pengguna berbasis Sertifikat
Pengaturan Penandatanganan Modul:
CREATE CERTIFICATE [AccessOtherDB]
ENCRYPTION BY PASSWORD = 'SomePassword'
WITH SUBJECT = 'Used for accessing other DB',
EXPIRY_DATE = '2099-12-31';
ADD SIGNATURE
TO dbo.[DataFromOtherDB]
BY CERTIFICATE [AccessOtherDB]
WITH PASSWORD = 'SomePassword';
---
DECLARE @CertificatePublicKey NVARCHAR(MAX) =
CONVERT(NVARCHAR(MAX), CERTENCODED(CERT_ID(N'AccessOtherDB')), 1);
SELECT @CertificatePublicKey AS [Cert / PublicKey]; -- debug
EXEC (N'USE [DatabaseB];
CREATE CERTIFICATE [AccessOtherDB] FROM BINARY = ' + @CertificatePublicKey + N';');
---
EXEC (N'
USE [DatabaseB];
CREATE USER [AccessOtherDbUser] FROM CERTIFICATE [AccessOtherDB];
GRANT SELECT ON dbo.[LotsOfValues] TO [AccessOtherDbUser];
');
---
EXECUTE AS LOGIN = 'RestrictedUser';
SELECT * FROM dbo.[DataFromOtherDB]();
-- Success!!
SELECT * FROM [DatabaseB].[dbo].[LotsOfValues];
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/
REVERT;
JIKA AKSES PERLU MELALUI PANDANGAN, untuk alasan apa pun, maka Anda dapat dengan mudah membuat Tampilan yang dipilih dari TVF yang ditunjukkan di atas. Dan, dalam situasi itu, SELECT
akses tidak perlu diberikan ke TVF, hanya ke View, seperti yang ditunjukkan di bawah ini:
GO
CREATE VIEW dbo.[DataFromTVF]
AS
SELECT [SomeValue]
FROM dbo.DataFromOtherDB();
GO
-- Remove direct access to the TVF as it is no longer needed:
REVOKE SELECT ON dbo.[DataFromOtherDB] FROM [RestrictedUser];
GRANT SELECT ON dbo.[DataFromTVF] TO [RestrictedUser];
Dan sekarang untuk mengujinya:
EXECUTE AS LOGIN = 'RestrictedUser';
SELECT * FROM dbo.[DataFromOtherDB]();
/*
Msg 229, Level 14, State 5, Line XXXXX
The SELECT permission was denied on the object 'DataFromOtherDB',
database 'DatabaseA', schema 'dbo'.
*/
SELECT * FROM [OwnershipChaining].[dbo].[LotsOfValues];
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/
SELECT * FROM dbo.[DataFromTVF];
-- Success!!
REVERT;
Untuk info lebih lanjut tentang Penandatanganan Modul, silakan kunjungi: https://ModuleSigning.Info/