SQL सर्वर सुरक्षा मॉडल आपको अंतर्निहित तालिकाओं तक पहुंच प्रदान किए बिना किसी दृश्य तक पहुंच प्रदान करने की अनुमति देता है।
चूंकि उदाहरण कोड एक अवधारणा को दिखाने का एक शानदार तरीका है, निम्नलिखित पर विचार करें, एक LoginDetails
तालिका, और इसी दृश्य के साथ:
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
हम एक लॉगिन और एक उपयोगकर्ता बनाएंगे, फिर उस उपयोगकर्ता को दृश्य से पंक्तियों का चयन करने का अधिकार प्रदान करेंगे, बिना किसी अधिकार के तालिका को देखने के लिए।
CREATE LOGIN RemoteUser
WITH PASSWORD = '2q1345lkjsadfgsa0(*';
CREATE USER RemoteUser
FOR LOGIN RemoteUser
WITH DEFAULT_SCHEMA = dbo;
GRANT SELECT ON dbo.LoginDetailsView TO RemoteUser;
अब, हम दो परीक्षण पंक्तियाँ डालेंगे:
INSERT INTO dbo.LoginDetails(Username, EmailAddress, LastLoggedInAt)
VALUES ('user x', 'x@y.com', NULL)
, ('user y', 'y@y.com', GETDATE());
यह सुरक्षा मॉडल का परीक्षण करता है। पहला SELECT
कथन सफल होता है, क्योंकि यह दृश्य से चयन कर रहा है, जबकि दूसरा SELECT
कथन विफल हो जाता है क्योंकि उपयोगकर्ता के पास तालिका तक सीधी पहुंच नहीं है।
EXECUTE AS LOGIN = 'RemoteUser';
SELECT *
FROM dbo.LoginDetailsView;
╔══════════╦══════════════╦═══════════════════════ ══╗
║ उपयोगकर्ता नाम A EmailAddress name LastLoggedInAt ║
╠══════════╬══════════════╬═══════════════════════ ══╣
║ उपयोगकर्ता y @ y@y.com -02 2018-02-15 07: 36: 54.490 ║
╚══════════╩══════════════╩═══════════════════════ ══╝
SELECT *
FROM dbo.LoginDetails;
REVERT
नोट देखने से परिणाम पंक्ति को बाहर जहां LastLoggedInAt
मूल्य है NULL
, के रूप में अपने प्रश्न में की आवश्यकता है।
SELECT
अंतर्निहित तालिका के विरुद्ध दूसरा कथन एक त्रुटि देता है:
Msg 229, Level 14, State 5, Line 28
सेलेक्ट अनुमति ऑब्जेक्ट 'LoginDetails', डेटाबेस 'tempdb', स्कीमा 'dbo' पर अस्वीकार की गई थी।
साफ - सफाई:
DROP USER RemoteUser;
DROP LOGIN RemoteUser;
DROP VIEW dbo.LoginDetailsView;
DROP TABLE dbo.LoginDetails;
वैकल्पिक रूप से, यदि आपके पास SQL सर्वर 2016 या नया है, तो आप कुछ उपयोगकर्ताओं को NULL LastLoggedInAt
मान वाली पंक्तियों को देखने से रोकने के लिए एक पंक्ति-स्तरीय-सुरक्षा-विधेय का उपयोग कर सकते हैं ।
सबसे पहले, हम तालिका बनाते हैं, एक लॉगिन, उस लॉगिन के लिए एक उपयोगकर्ता, और हम तालिका तक पहुंच प्रदान करते हैं:
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;
अगला, हम नमूना पंक्तियों के एक जोड़े को सम्मिलित करते हैं। एक नल के साथ एक पंक्ति LastLoggedInAt
, और उस कॉलम के लिए गैर-शून्य मान के साथ एक।
INSERT INTO dbo.LoginDetails(Username, EmailAddress, LastLoggedInAt)
VALUES ('user x', 'x@y.com', NULL)
, ('user y', 'y@y.com', GETDATE());
यहां, हम एक स्कीमा-बाउंड टेबल-वैल्यू-फंक्शन बना रहे हैं, जो फ़ंक्शन में दिए गए वेरिएबल @LastLoggedInAt
और @username
वेरिएबल्स के मूल्य के आधार पर या तो 0 या 1 के साथ एक पंक्ति देता है । इस फ़ंक्शन का उपयोग फ़िल्टर-विधेय द्वारा उन पंक्तियों को समाप्त करने के लिए किया जाएगा जिन्हें हम कुछ उपयोगकर्ताओं से छिपाना चाहते हैं।
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
यह सुरक्षा फ़िल्टर है SELECT
जो dbo.LoginDetails
तालिका के विरुद्ध चलाए गए कथनों से पंक्तियों को समाप्त करता है:
CREATE SECURITY POLICY LoginDetailsRemoteUserPolicy
ADD FILTER PREDICATE dbo.fn_LoginDetailsRemoteUserPredicate(LastLoggedInAt, USER_NAME())
ON dbo.LoginDetails
WITH (STATE=ON);
उपरोक्त फ़िल्टर तालिका से स्तंभ के dbo.fn_LoginDetailsRemoteUserPredicate
लिए प्रत्येक पंक्ति के मानों के साथ, वर्तमान उपयोगकर्ता के नाम से गुजरकर फ़ंक्शन का उपयोग करता है ।LastLoggedInAt
dbo.LoginDetails
यदि हम सामान्य उपयोगकर्ता के रूप में तालिका को क्वेरी करते हैं:
SELECT *
FROM dbo.LoginDetails
हम सभी पंक्तियों को देखते हैं:
╔══════════╦══════════════╦═══════════════════════ ══╗
║ उपयोगकर्ता नाम A EmailAddress name LastLoggedInAt ║
╠══════════╬══════════════╬═══════════════════════ ══╣
║ उपयोगकर्ता x x x@y.com ║ NULL ║
║ उपयोगकर्ता y @ y@y.com -02 2018-02-15 13: 53: 42.577 ║
╚══════════╩══════════════╩═══════════════════════ ══╝
हालाँकि, अगर हम परीक्षण करते हैं RemoteUser
:
EXECUTE AS LOGIN = 'RemoteUser';
SELECT *
FROM dbo.LoginDetails
REVERT
हम केवल "मान्य" पंक्तियाँ देखते हैं:
╔══════════╦══════════════╦═══════════════════════ ══╗
║ उपयोगकर्ता नाम A EmailAddress name LastLoggedInAt ║
╠══════════╬══════════════╬═══════════════════════ ══╣
║ उपयोगकर्ता y @ y@y.com -02 2018-02-15 13: 42: 02.023 ║
╚══════════╩══════════════╩═══════════════════════ ══╝
और, हम साफ करते हैं:
DROP SECURITY POLICY LoginDetailsRemoteUserPolicy;
DROP FUNCTION dbo.fn_LoginDetailsRemoteUserPredicate;
DROP USER RemoteUser;
DROP LOGIN RemoteUser;
DROP TABLE dbo.LoginDetails;
इस बात से अवगत रहें कि स्कीमा को इस तरह से टेबल पर बाँधना एक फंक्शन को पहले से छानने के बिना टेबल की परिभाषा को संशोधित करना असंभव बनाता है, और dbo.fn_LoginDetailsRemoteUserPredicate
फ़ंक्शन को।