SQL Server güvenlik modeli, temel tablolara erişim izni vermeden bir görünüme erişim izni vermenizi sağlar.
Örnek kod bir kavramı göstermek için harika bir yol olduğundan, LoginDetails
tablo ve karşılık gelen görünümle aşağıdakileri göz önünde bulundurun :
CREATE TABLE dbo.LoginDetails
(
Username nvarchar(100) NOT NULL
, EmailAddress nvarchar(256) NOT NULL
, LastLoggedInAt datetime NULL
);
GO
CREATE VIEW dbo.LoginDetailsView
AS
SELECT ld.Username
, ld.EmailAddress
, ld.LastLoggedInAt
FROM dbo.LoginDetails ld
WHERE ld.LastLoggedInAt IS NOT NULL;
GO
Bir giriş ve bir kullanıcı oluşturacağız, ardından bu kullanıcıya, tablonun kendisini görüntüleme hakları olmadan görünümden satır seçme hakları atayacağız.
CREATE LOGIN RemoteUser
WITH PASSWORD = '2q1345lkjsadfgsa0(*';
CREATE USER RemoteUser
FOR LOGIN RemoteUser
WITH DEFAULT_SCHEMA = dbo;
GRANT SELECT ON dbo.LoginDetailsView TO RemoteUser;
Şimdi iki test satırı ekleyeceğiz:
INSERT INTO dbo.LoginDetails(Username, EmailAddress, LastLoggedInAt)
VALUES ('user x', 'x@y.com', NULL)
, ('user y', 'y@y.com', GETDATE());
Bu, güvenlik modelini test eder. İlk SELECT
ifade, görünümden seçtiği için başarılı olurken, ikinci SELECT
tablo, kullanıcının tabloya doğrudan erişimi olmadığından başarısız olur.
EXECUTE AS LOGIN = 'RemoteUser';
SELECT *
FROM dbo.LoginDetailsView;
╔══════════╦══════════════╦═══════════════════════ ══╗
║ Kullanıcı Adı ║ EmailAddress ║ LastLoggedInAt ║
╠══════════╬══════════════╬═══════════════════════ ══╣
║ kullanıcı y ║ y@y.com ║ 2018-02-15 07: 36: 54.490 ║
╚══════════╩══════════════╩═══════════════════════ ══╝
SELECT *
FROM dbo.LoginDetails;
REVERT
Görünümdeki sonuçların , sorunuzun gerektirdiği şekilde LastLoggedInAt
değerin olduğu satırı hariç tuttuğunu NULL
unutmayın.
SELECT
Temel tabloya karşı ikinci ifade bir hata döndürür:
Msg 229, Seviye 14, Durum 5, Satır 28
'LoginDetails', 'tempdb' veritabanı, 'dbo' şeması nesnesinde SELECT izni reddedildi.
Temizlemek:
DROP USER RemoteUser;
DROP LOGIN RemoteUser;
DROP VIEW dbo.LoginDetailsView;
DROP TABLE dbo.LoginDetails;
Alternatif olarak, SQL Server 2016 veya daha yeni bir sürümünüz varsa, belirli kullanıcıların NULL LastLoggedInAt
değerine sahip satırları görmesini engellemek için satır düzeyinde güvenlik tahmini kullanabilirsiniz .
İlk olarak, tabloyu, bir girişi, o giriş için bir kullanıcı yaratırız ve tabloya erişim veririz:
CREATE TABLE dbo.LoginDetails
(
Username nvarchar(100) NOT NULL
, EmailAddress nvarchar(256) NOT NULL
, LastLoggedInAt datetime NULL
);
GO
CREATE LOGIN RemoteUser
WITH PASSWORD = '2q1345lkjsadfgsa0(*';
CREATE USER RemoteUser
FOR LOGIN RemoteUser
WITH DEFAULT_SCHEMA = dbo;
GRANT SELECT ON dbo.LoginDetails TO RemoteUser;
Ardından, birkaç örnek satır ekliyoruz. Bir satırda null LastLoggedInAt
ve bir satırda null olmayan değer.
INSERT INTO dbo.LoginDetails(Username, EmailAddress, LastLoggedInAt)
VALUES ('user x', 'x@y.com', NULL)
, ('user y', 'y@y.com', GETDATE());
Burada, işleve iletilen değişkenlere @LastLoggedInAt
ve @username
değişkenlere bağlı olarak 0 veya 1 ile bir satır döndüren şemaya bağlı tablo değerli bir işlev oluşturuyoruz. Bu işlev, belirli kullanıcılardan gizlemek istediğimiz satırları ortadan kaldırmak için bir filtre tahmini tarafından kullanılır.
CREATE FUNCTION dbo.fn_LoginDetailsRemoteUserPredicate
(
@LastLoggedInAt datetime
, @username sysname
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_securitypredicate_result
WHERE (@username = N'RemoteUser' AND @LastLoggedInAt IS NOT NULL)
OR @username <> N'RemoteUser';
GO
Bu, tabloya SELECT
karşı çalıştırılan ifadelerden satırları ortadan kaldıran güvenlik filtresidir dbo.LoginDetails
:
CREATE SECURITY POLICY LoginDetailsRemoteUserPolicy
ADD FILTER PREDICATE dbo.fn_LoginDetailsRemoteUserPredicate(LastLoggedInAt, USER_NAME())
ON dbo.LoginDetails
WITH (STATE=ON);
Yukarıdaki filtre , tablodaki sütun dbo.fn_LoginDetailsRemoteUserPredicate
için her satırdaki değerlerle birlikte geçerli kullanıcının adını ileterek işlevi kullanır .LastLoggedInAt
dbo.LoginDetails
Tabloyu normal kullanıcı olarak sorgularsak:
SELECT *
FROM dbo.LoginDetails
tüm satırları görüyoruz:
╔══════════╦══════════════╦═══════════════════════ ══╗
║ Kullanıcı Adı ║ EmailAddress ║ LastLoggedInAt ║
╠══════════╬══════════════╬═══════════════════════ ══╣
║ kullanıcı x ║ x@y.com ║ NULL ║
║ kullanıcı y ║ y@y.com ║ 2018-02-15 13: 53: 42.577 ║
╚══════════╩══════════════╩═══════════════════════ ══╝
Ancak, şu şekilde test edersek RemoteUser
:
EXECUTE AS LOGIN = 'RemoteUser';
SELECT *
FROM dbo.LoginDetails
REVERT
yalnızca "geçerli" satırlar görüyoruz:
╔══════════╦══════════════╦═══════════════════════ ══╗
║ Kullanıcı Adı ║ EmailAddress ║ LastLoggedInAt ║
╠══════════╬══════════════╬═══════════════════════ ══╣
║ kullanıcı y ║ y@y.com ║ 2018-02-15 13: 42: 02.023 ║
╚══════════╩══════════════╩═══════════════════════ ══╝
Ve temizliyoruz:
DROP SECURITY POLICY LoginDetailsRemoteUserPolicy;
DROP FUNCTION dbo.fn_LoginDetailsRemoteUserPredicate;
DROP USER RemoteUser;
DROP LOGIN RemoteUser;
DROP TABLE dbo.LoginDetails;
Şema bağlamanın bir işlevi bu şekilde tabloya bağlamanın, önce filtre yüklemini ve dbo.fn_LoginDetailsRemoteUserPredicate
işlevi düşürmeden tablonun tanımını değiştirmeyi imkansız hale getirdiğini unutmayın .