โปรดอย่าใช้ 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
อย่างไรก็ตามฟังก์ชั่นนี้จะไม่มีประโยชน์ใด ๆ ในตัวอย่างด้านบน