Aracılığıyla paylaş


Öğretici: Sahiplik Zincirleri ve Bağlam Değiştirme

Şunlar için geçerlidir:SQL ServerAzure SQL Yönetilen Örneği

Bu öğreticide, sahiplik zincirleri ve kullanıcı bağlamı değiştirme ile ilgili SQL Server güvenlik kavramlarını göstermek için bir senaryo kullanılır.

Uyarı

Bu öğreticideki kodu çalıştırmak için hem Karma Mod güvenliğinin yapılandırılmış hem de veritabanının AdventureWorks2025 yüklü olması gerekir. Karma Mod güvenliği hakkında daha fazla bilgi için bkz. Kimlik Doğrulama Modu Seçme.

Scenario

Bu senaryoda, iki kullanıcının veritabanında depolanan satın alma siparişi verilerine erişmek için hesaplara AdventureWorks2025 ihtiyacı vardır. Gereksinimler şunlardır:

  • İlk hesabın (TestManagerUser) her satın alma siparişindeki tüm ayrıntıları görebilmesi gerekir.
  • İkinci hesabın (TestEmployeeUser), kısmi sevkiyatların alındığı ürünler için satınalma siparişi numarası, sipariş tarihi, sevkiyat tarihi, ürün kimliği numaraları ve satınalma siparişi başına sipariş edilen ve alınan ürünleri, satınalma siparişi numarasına göre görebilmesi gerekir.
  • Diğer tüm hesapların geçerli izinlerini koruması gerekir.
    Bu senaryonun gereksinimlerini karşılamak için örnek, sahiplik zincirleri ve bağlam değiştirme kavramlarını gösteren dört bölüme ayrılmıştır:
  1. Ortamı yapılandırma.
  2. Satın alma siparişine göre verilere erişmek için saklı yordam oluşturma.
  3. Saklı yordam aracılığıyla verilere erişme.
  4. Ortamı sıfırlama.

Bu örnekteki her kod bloğu satır içinde açıklanmıştır. Tam örneği kopyalamak için bu öğreticinin sonundaki Tam Örnek bölümüne bakın.

Önkoşullar

Bu öğreticiyi tamamlamak için SQL Server Management Studio, SQL Server çalıştıran bir sunucuya ve bir AdventureWorks2025 veritabanına erişiminiz olmalıdır.

SQL Server Management Studio'da veritabanını geri yükleme yönergeleri için bkz. Veritabanını geri yükleme.

1. Ortamı Yapılandırma

SQL Server Management Studio'yu ve aşağıdaki kodu kullanarak AdventureWorks2025 veritabanını açın ve dbo kullanıcısının CURRENT_USER bağlam olarak görüntülenip görüntülenmediğini kontrol etmek için Transact-SQL ifadesini kullanın.

USE AdventureWorks2022;  
GO  
SELECT CURRENT_USER AS 'Current User Name';  
GO  

CURRENT_USER deyimi hakkında daha fazla bilgi için bkz. CURRENT_USER (Transact-SQL).

Bu kodu dbo kullanıcısı olarak kullanarak sunucuda ve AdventureWorks2025 veritabanında iki kullanıcı oluşturun.

CREATE LOGIN TestManagerUser   
    WITH PASSWORD = '340$Uuxwp7Mcxo7Khx';  
GO  
CREATE USER TestManagerUser   
   FOR LOGIN TestManagerUser  
   WITH DEFAULT_SCHEMA = Purchasing;  
GO   
  
CREATE LOGIN TestEmployeeUser  
    WITH PASSWORD = '340$Uuxwp7Mcxo7Khy';  
GO  
CREATE USER TestEmployeeUser   
   FOR LOGIN TestEmployeeUser;  
GO   

CREATE USER deyimi hakkında daha fazla bilgi için bkz. CREATE USER (Transact-SQL). CREATE LOGIN deyimi hakkında daha fazla bilgi için bkz. CREATE LOGIN (Transact-SQL).

Purchasing şemasının sahipliğini TestManagerUser hesabına değiştirmek için aşağıdaki kodu kullanın. Bu, hesabın içerdiği nesneler üzerinde tüm Veri İşleme Dili (DML) deyimlerine erişim (örneğin, SELECT ve INSERT izinleri) sağlamasına olanak tanır. TestManagerUser saklı yordamlar oluşturma yetkisi de verilir.

/* Change owner of the Purchasing Schema to TestManagerUser */  
ALTER AUTHORIZATION   
   ON SCHEMA::Purchasing   
   TO TestManagerUser;  
GO  
  
GRANT CREATE PROCEDURE   
   TO TestManagerUser   
   WITH GRANT OPTION;  
GO  

GRANT deyimi hakkında daha fazla bilgi için bkz . GRANT (Transact-SQL). Saklı yordamlar hakkında daha fazla bilgi için bkz . Saklı Yordamlar (Veritabanı Altyapısı). Tüm Veritabanı Altyapısı izinlerinin posteri için bkz https://aka.ms/sql-permissions-poster. .

2. Verilere Erişmek için Saklı Yordam Oluşturma

Veritabanında bağlam değiştirmek için EXECUTE AS deyimini kullanın. EXECUTE AS, TAKLİT izinleri gerektirir.

Aşağıdaki kodda EXECUTE AS deyimini kullanarak, bağlamı TestManagerUser olarak değiştirin ve yalnızca TestEmployeeUser tarafından gereken verileri gösteren bir saklı yordam oluşturun. Gereksinimleri karşılamak için saklı prosedür, satınalma siparişi numarası için bir değişken kabul eder, finansal bilgileri görüntülemez; WHERE şartı ise sonuçları kısmi sevkiyatlarla sınırlar.

EXECUTE AS LOGIN = 'TestManagerUser'  
GO  
SELECT CURRENT_USER AS 'Current User Name';  
GO  
  
/* Note: The user that calls the EXECUTE AS statement must have IMPERSONATE permissions on the target principal */  
CREATE PROCEDURE usp_ShowWaitingItems @ProductID int  
AS  
BEGIN   
   SELECT a.PurchaseOrderID, a.OrderDate, a.ShipDate  
      , b.ProductID, b.OrderQty, b.ReceivedQty  
   FROM Purchasing.PurchaseOrderHeader a  
      INNER JOIN Purchasing.PurchaseOrderDetail b  
         ON a.PurchaseOrderID = b.PurchaseOrderID  
   WHERE b.OrderQty > b.ReceivedQty  
      AND @ProductID = b.ProductID  
   ORDER BY b.ProductID ASC  
END  
GO  

Şu anda TestEmployeeUser hiçbir veritabanı nesnesine erişimi yoktur. Aşağıdaki kod (hala TestManagerUser bağlamdadır), kullanıcı hesabına saklı yordam aracılığıyla temel tablo bilgilerini sorgulama olanağı verir.

GRANT EXECUTE  
   ON OBJECT::Purchasing.usp_ShowWaitingItems  
   TO TestEmployeeUser;  
GO  

Saklı yordam, Purchasing varsayılan olarak TestManagerUser şemasına atandığı için, herhangi bir şema açıkça belirtilmemiş olsa da Purchasing şemasının bir parçasıdır. Aşağıdaki kodda gösterildiği gibi nesneleri bulmak için sistem kataloğu bilgilerini kullanabilirsiniz.

SELECT a.name AS 'Schema'  
   , b.name AS 'Object Name'  
   , b.type AS 'Object Type'  
FROM sys.schemas a  
   INNER JOIN sys.objects b  
      ON a.schema_id = b.schema_id   
WHERE b.name = 'usp_ShowWaitingItems';  
GO  

Örneğin bu bölümü tamamladıktan sonra kod, REVERT deyimini kullanarak bağlamı dbo'ya geri döndürür.

REVERT;  
GO  

REVERT deyimi hakkında daha fazla bilgi için bkz. REVERT (Transact-SQL).

3. Saklı Yordam Kullanarak Verilere Erişme

TestEmployeeUser oturum açma bilgileri ve genel veritabanı rolüne atanan haklar dışında veritabanı nesneleri üzerinde AdventureWorks2025 hiçbir izni yoktur. Aşağıdaki kod, temel tablolara erişmeye çalışırken TestEmployeeUser bir hata döndürür.

EXECUTE AS LOGIN = 'TestEmployeeUser'  
GO  
SELECT CURRENT_USER AS 'Current User Name';  
GO  
/* This won't work */  
SELECT *  
FROM Purchasing.PurchaseOrderHeader;  
GO  
SELECT *  
FROM Purchasing.PurchaseOrderDetail;  
GO  

Geri döndürülen hata:

Msg 229, Level 14, State 5, Line 6
The SELECT permission was denied on the object 'PurchaseOrderHeader', database 'AdventureWorks2022', schema 'Purchasing'.

Son bölümde oluşturulan saklı yordam tarafından başvurulan nesneler, TestManagerUser şema sahipliğine bağlı olarak Purchasing tarafından sahiplenildiğinden, TestEmployeeUser saklı yordam aracılığıyla temel tablolara erişebilir. TestEmployeeUser bağlamını kullanmaya devam eden aşağıdaki kod, satın alma siparişi 952'yi parametre olarak geçirir.

EXEC Purchasing.usp_ShowWaitingItems 952  
GO  

4. Ortamı Sıfırlama

Aşağıdaki kod, geçerli hesabın bağlamını REVERT komutunu kullanarak dbo öğesine geri döndürür ve ardından ortamı sıfırlar.

REVERT;  
GO  
ALTER AUTHORIZATION   
ON SCHEMA::Purchasing TO dbo;  
GO  
DROP PROCEDURE Purchasing.usp_ShowWaitingItems;  
GO  
DROP USER TestEmployeeUser;  
GO  
DROP USER TestManagerUser;  
GO  
DROP LOGIN TestEmployeeUser;  
GO  
DROP LOGIN TestManagerUser;  
GO  

Tam Örnek

Bu bölümde örnek kodun tamamı görüntülenir.

Uyarı

Bu kod, TestEmployeeUser'ün temel tablolardan seçim yapamamasını gösteren beklenen iki hatayı barındırmaz.

/*   
Script:       UserContextTutorial.sql  
Author:       Microsoft  
Last Updated: Books Online  
Conditions:   Execute as DBO or sysadmin in the AdventureWorks database  
Section 1:    Configure the Environment   
*/  
USE AdventureWorks2022;  
GO  
SELECT CURRENT_USER AS 'Current User Name';  
GO  
/* Create server and database users */  
CREATE LOGIN TestManagerUser   
    WITH PASSWORD = '340$Uuxwp7Mcxo7Khx';  
  
GO  
  
CREATE USER TestManagerUser   
   FOR LOGIN TestManagerUser  
   WITH DEFAULT_SCHEMA = Purchasing;  
GO   
  
CREATE LOGIN TestEmployeeUser  
    WITH PASSWORD = '340$Uuxwp7Mcxo7Khy';  
GO  
CREATE USER TestEmployeeUser   
   FOR LOGIN TestEmployeeUser;  
GO   
  
/* Change owner of the Purchasing Schema to TestManagerUser */  
ALTER AUTHORIZATION   
   ON SCHEMA::Purchasing   
   TO TestManagerUser;  
GO  
  
GRANT CREATE PROCEDURE   
   TO TestManagerUser   
   WITH GRANT OPTION;  
GO  
  
/*   
Section 2: Switch Context and Create Objects  
*/  
EXECUTE AS LOGIN = 'TestManagerUser';  
GO  
SELECT CURRENT_USER AS 'Current User Name';  
GO  
  
/* Note: The user that calls the EXECUTE AS statement must have IMPERSONATE permissions on the target principal */  
CREATE PROCEDURE usp_ShowWaitingItems @ProductID int  
AS  
BEGIN   
   SELECT a.PurchaseOrderID, a.OrderDate, a.ShipDate  
      , b.ProductID, b.OrderQty, b.ReceivedQty  
   FROM Purchasing.PurchaseOrderHeader AS a  
      INNER JOIN Purchasing.PurchaseOrderDetail AS b  
         ON a.PurchaseOrderID = b.PurchaseOrderID  
   WHERE b.OrderQty > b.ReceivedQty  
      AND @ProductID = b.ProductID  
   ORDER BY b.ProductID ASC  
END;  
GO  
  
/* Give the employee the ability to run the procedure */  
GRANT EXECUTE   
   ON OBJECT::Purchasing.usp_ShowWaitingItems  
   TO TestEmployeeUser;  
GO   
  
/* Notice that the stored procedure is located in the Purchasing   
schema. This also demonstrates system catalogs */  
SELECT a.name AS 'Schema'  
   , b.name AS 'Object Name'  
   , b.type AS 'Object Type'  
FROM sys.schemas AS a  
   INNER JOIN sys.objects AS b  
      ON a.schema_id = b.schema_id   
WHERE b.name = 'usp_ShowWaitingItems';  
GO  
  
/* Go back to being the dbo user */  
REVERT;  
GO  
  
/*  
Section 3: Switch Context and Observe Security   
*/  
EXECUTE AS LOGIN = 'TestEmployeeUser';  
GO  
SELECT CURRENT_USER AS 'Current User Name';  
GO  
EXEC Purchasing.usp_ShowWaitingItems 952;  
GO  
  
/*   
Section 4: Clean Up Example  
*/  
REVERT;  
GO  
ALTER AUTHORIZATION   
ON SCHEMA::Purchasing TO dbo;  
GO  
DROP PROCEDURE Purchasing.usp_ShowWaitingItems;  
GO  
DROP USER TestEmployeeUser;  
GO  
DROP USER TestManagerUser;  
GO  
DROP LOGIN TestEmployeeUser;  
GO  
DROP LOGIN TestManagerUser;  
GO  

Ayrıca Bkz.

SQL Server Veritabanı Altyapısı ve Azure SQL Veritabanı için Güvenlik Merkezi