SQL सर्वर पंक्ति पंक्ति अभिगम द्वारा


10

मेरे पास एक संरचित तालिका है (सरलीकृत)

Name, EMail, LastLoggedInAt

मेरे पास SQL ​​सर्वर (RemoteUser) में एक उपयोगकर्ता है जो केवल डेटा (वाया एक चुनिंदा क्वेरी) को देखने में सक्षम होना चाहिए जहां LastLoggdInAt फ़ील्ड शून्य नहीं है।

ऐसा लगता है कि मैं ऐसा कर सकता हूं? क्या यह संभव है?


यहां पंक्ति-स्तरीय सुरक्षा के लिए पुस्तकें ऑनलाइन विषय: docs.microsoft.com/en-us/sql/relational-dat डेटाबेस
डेविड ब्राउन - Microsoft

जवाबों:


32

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लिए प्रत्येक पंक्ति के मानों के साथ, वर्तमान उपयोगकर्ता के नाम से गुजरकर फ़ंक्शन का उपयोग करता है ।LastLoggedInAtdbo.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फ़ंक्शन को।


शानदार जवाब - धन्यवाद! इन 2 विधियों के प्रदर्शन निहितार्थ को व्हाट्सएप करें। हमने पाया है कि जब हम फ़ंक्शन का उपयोग करते हैं तो हमारा वेब ऐप 5 गुना धीमा होता है। व्यू मेथड को देखने की जरूरत है।
लियाम

पंक्ति-स्तर-सुरक्षा फ़ंक्शन का मूल्यांकन तालिका से पढ़ी गई प्रत्येक पंक्ति के लिए किया जाता है; मुझे उम्मीद है कि यह उस तालिका में काफी धीमी गति से पहुंच प्राप्त करेगा। दूसरी ओर, दृश्य को प्रदर्शन पर नगण्य प्रभाव होना चाहिए, यह मानते हुए कि आप LastLoggedInAtस्तंभ पर एक उपयोगी सूचकांक बनाते हैं ।
मैक्स वर्नोन

यह समझ में आता है - मैं अब इस दृश्य को देखूंगा, लगता है कि यह अच्छी तरह से काम कर रहा है! यदि हम चाहते थे कि उपयोगकर्ता इन पंक्तियों के लिए केवल उपयोगकर्ता डेटा को संपादित करने में सक्षम हो जो कि मापदंड से मेल खाता हो तो क्या यह संभव है?
लियाम

इसका सुंदर, सभी काम - इस के साथ मदद के लिए धन्यवाद
LiamB

हां, आप दृश्य के माध्यम से पंक्तियों को संपादित कर सकते हैं
मैक्स वर्नोन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.