วิธีเพิ่มผู้ใช้ด้วยการเข้าถึงมุมมองเดียว?


14

ฉันทำงานกับ MSSQL Server Management Studio 2008 และฉันจำเป็นต้องเปิดเผยมุมมองต่อบุคคลที่สามสำหรับการปรับยอดข้อมูลให้ตรงกัน ฉันสร้างมุมมองที่เหมาะสม แต่ฉันมีปัญหาในการสร้างผู้ใช้และให้สิทธิ์ที่เหมาะสมแก่ผู้ใช้ในการเลือกจากมุมมอง

ฉันติดตามพ่อมดเพื่อสร้างการเข้าสู่ระบบและผู้ใช้แล้วเพิ่มมุมมองของฉันในส่วนที่ปลอดภัยด้วยกล่องสิทธิ์ที่เลือกไว้ ทุกอย่างดูเหมือนจะดี แต่เมื่อฉันเข้าสู่ระบบในฐานะผู้ใช้นั้นและพยายามที่จะทำ "เลือก * จาก MyViewName" มันบอกฉันว่าการอนุญาตเลือกถูกปฏิเสธ

ฉันเพิ่งสร้างผู้ใช้ใหม่ (คราวนี้ใช้ SQL แทนตัวช่วยสร้าง) และได้รับการอนุญาตอย่างชัดเจนและตอนนี้มันทำให้ฉันเกิดข้อผิดพลาด: Msg 916, Level 14, State 1, Line 2 The server principal "username" is not able to access the database "unrelated_db" under the current security context.(ฉันไม่รู้ว่าทำไมมันถึงพยายามเข้าถึงฐานข้อมูลที่ไม่เกี่ยวข้อง ... )

ฉันไม่รู้จะไปจากที่นี่จริงๆ อีกครั้งโดยพื้นฐานทั้งหมดที่ฉันต้องการคือการสร้างผู้ใช้ที่ฉันสามารถมอบให้กับบุคคลที่สามเพื่อให้พวกเขาเชื่อมต่อกับฐานข้อมูลของเราและเลือกจากมุมมองนี้


3
มุมมองอ้างอิงตารางฐานในฐานข้อมูลอื่น ๆ หรือไม่? ถ้าเป็นเช่นนั้นคุณจะต้องจัดการกับการผูกมัดเจ้าของ ตรวจสอบให้แน่ใจว่าคุณมีบริบทฐานข้อมูลที่ตั้งค่าเป็นฐานข้อมูลที่ต้องการ
Thomas Stringer

มีวิธีดูการอ้างอิงสำหรับมุมมองหรือไม่? ฉันหมายถึงเท่าที่ฉันรู้ทุกอย่างจากมุมมองควรอยู่ในฐานข้อมูลหลัก มุมมองเป็นเพียงสามฟิลด์สองมาจากตารางรายละเอียดการชำระเงินและอีกหนึ่งมาจากการเข้าร่วมในตารางรายละเอียดบัญชี แต่ตารางทั้งสองอยู่ในฐานข้อมูลเดียวกัน (และฐานข้อมูลเดียวกันกับมุมมอง)
velojason

คำตอบ:


16

โปรดอย่าใช้ UI สำหรับสิ่งนี้ มันเป็นเรื่องสับสน

ฟังดูเหมือนว่าสิ่งที่คุณต้องการคือการสร้างผู้ใช้ในฐานข้อมูลสำหรับการเข้าสู่ระบบเฉพาะที่มีสิทธิ์ในการเลือกจากมุมมองเดียว ดังนั้นเนื่องจากคุณได้สร้างชื่อเข้าสู่ระบบแล้ว:

USE your_db;
GO
CREATE USER username FROM LOGIN username;
GO
GRANT SELECT ON dbo.MyViewName TO username;
GO

แก้ไขที่นี่เป็นตัวอย่างของสคริปต์ที่จะนำไปสู่ข้อผิดพลาดที่คุณพูดถึง

ก่อนอื่นให้สร้างตารางใน unrelated_db:

CREATE DATABASE unrelated_db;
GO
USE unrelated_db;
GO
CREATE TABLE dbo.foo(bar INT);
GO

ตอนนี้สร้างการเข้าสู่ระบบที่ค่อนข้าง จำกัด :

USE [master];
GO
CREATE LOGIN username WITH PASSWORD='foo', CHECK_POLICY = OFF;
GO

ตอนนี้สร้างฐานข้อมูลที่มุมมองจะมีชีวิตอยู่และเพิ่มการเข้าสู่ระบบในฐานะผู้ใช้:

CREATE DATABASE velojason;
GO
USE velojason;
GO
CREATE USER username FROM LOGIN username;
GO

ตอนนี้สร้างฟังก์ชั่นที่จะอ้างอิงตารางในฐานข้อมูลอื่นและคำพ้องกับตารางอื่น:

CREATE FUNCTION dbo.checkbar()
RETURNS INT
AS 
BEGIN
    RETURN 
    (
      SELECT TOP (1) bar 
        FROM unrelated_db.dbo.foo 
        ORDER BY bar
    );
END
GO
CREATE SYNONYM dbo.foo FOR unrelated_db.dbo.foo;
GO

ตอนนี้สร้างตารางท้องถิ่น:

CREATE TABLE dbo.PaymentDetails
(
  PaymentID INT
);
GO

ตอนนี้สร้างมุมมองที่อ้างอิงถึงตารางฟังก์ชั่นและคำพ้องความหมายและให้SELECTกับusername:

CREATE VIEW dbo.SomeView
AS
  SELECT 
    p.PaymentID, 
    x = dbo.checkbar(), -- function that pulls from other DB
    y = (SELECT bar FROM dbo.foo) -- synonym to other DB
    FROM dbo.PaymentDetails AS p;
GO
GRANT SELECT ON dbo.SomeView TO username;
GO

ตอนนี้พยายามที่จะดำเนินการเป็นusernameและเลือกเฉพาะคอลัมน์ท้องถิ่นจากมุมมอง:

EXECUTE AS USER = 'username';
GO
  -- even though I don't reference any of the columns 
  -- in the other DB, I am denied SELECT on the view:
SELECT PaymentID FROM dbo.SomeView;
GO
REVERT;
GO

ผลลัพธ์:

ข่าวสารเกี่ยวกับ 916, ระดับ 14, สถานะ 1, บรรทัด 3
เซิร์ฟเวอร์ "ชื่อผู้ใช้" หลักไม่สามารถเข้าถึงฐานข้อมูล "unrelated_db" ภายใต้บริบทความปลอดภัยปัจจุบัน

ตอนนี้เปลี่ยนมุมมองเพื่อไม่อ้างอิงวัตถุภายนอกใด ๆ และเรียกใช้ข้างต้นSELECTอีกครั้งและทำงาน:

ALTER VIEW dbo.SomeView
AS
  SELECT 
    p.PaymentID 
    --x = dbo.checkbar(),
    --y = (SELECT bar FROM dbo.foo)
    FROM dbo.PaymentDetails AS p;
GO

ย่อแสดงสคริปต์สำหรับรายละเอียดการชำระเงินรายละเอียดบัญชีและวัตถุ MyView คุณอาจแจ้งให้เราทราบหากแบบสอบถามนี้ส่งคืนผลลัพธ์ใด ๆ คุณสามารถค้นหาการอ้างอิงไปยังวัตถุต่าง ๆ ผ่านมุมมองแคตตาล็อกsys.sql_expression_dependenciesแต่มุมมองนี้ไม่สมบูรณ์ - ฉันเชื่อว่ามันขึ้นอยู่กับมุมมองทั้งหมดที่ถูกรีเฟรช (ในกรณีที่มุมมองที่อ้างอิงมุมมองอื่น ๆ ตัวอย่างเช่น เพื่อความถูกต้อง

DECLARE 
  @dbname   SYSNAME = N'unrelated_db',
  @viewname SYSNAME = N'dbo.SomeView';

SELECT DISTINCT 
    [This object] = 
    OBJECT_SCHEMA_NAME([referencing_id]) 
      + '.' + OBJECT_NAME([referencing_id]), 
    [references this object] = 
    OBJECT_SCHEMA_NAME([referenced_id]) 
      + '.' + OBJECT_NAME([referenced_id]), 
    [and touches this database] = referenced_database_name,
    [and is a(n)] = o.type_desc,
    [if synonym, it references] = s.base_object_name
FROM sys.sql_expression_dependencies AS d
LEFT OUTER JOIN sys.objects AS o
ON o.[object_id] = d.referenced_id
LEFT OUTER JOIN sys.synonyms AS s
ON d.referenced_id = s.[object_id]
AND s.base_object_name LIKE '%[' + @dbname + ']%'
WHERE OBJECT_ID(@viewname) IN (
        referenced_id, 
        referencing_id, 
        (SELECT referencing_id FROM sys.sql_expression_dependencies 
        WHERE referenced_database_name = @dbname)
) OR referenced_database_name = @dbname;

SQL Server ไม่เพียง แต่จะพยายามเข้าถึงunrelated_dbเพื่อความสนุกเท่านั้น ... ต้องมีการผูกกับฐานข้อมูลนั้นจากมุมมองที่คุณพยายามใช้ น่าเสียดายถ้าเราไม่เห็นคำจำกัดความมุมมองและรายละเอียดเพิ่มเติมเกี่ยวกับวัตถุที่สัมผัสสิ่งที่เราทำได้ก็คือการคาดเดา สองสิ่งหลักที่ฉันนึกได้คือคำพ้องความหมายหรือฟังก์ชั่นที่ใช้ชื่อสามส่วน แต่การได้เห็นสคริปต์จริงจะทำให้เรามีความคิดที่ดีกว่าแทนที่จะคาดเดา :-)

คุณอาจต้องการตรวจสอบsys.dm_sql_referenced_entitiesอย่างไรก็ตามฟังก์ชั่นนี้จะไม่มีประโยชน์ใด ๆ ในตัวอย่างด้านบน


6
create login YourTpvLogin with password = 'enter new password here'
go

use SomeDb
go

create user YourTpvUser for login YourTpvLogin
go

grant select on YourView to YourTpvUser
go

คุณสามารถทดสอบสิ่งนี้ได้โดยทำสิ่งต่อไปนี้:

execute as user = 'YourTpvUser'
go

select *
from YourView

revert
go

เห็นได้ชัดว่านี่ไม่ได้ให้สิทธิ์พิเศษซ้ำ ๆ ผู้ใช้ได้รับอนุญาตให้เลือกจาก "YourView" แต่ถ้า "YourView" ขึ้นอยู่กับความสัมพันธ์ / ฐานข้อมูลอื่นมันจะล้มเหลว: เซิร์ฟเวอร์หลัก "YourTpvUser" ไม่สามารถเข้าถึงฐานข้อมูล "OtherDb" ภายใต้บริบทความปลอดภัยปัจจุบัน
lilalinux
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.