Tsql 如何在SQL Server 2016中对明细表实现安全筛选器谓词
下面是我们如何在SQL Server 2016中实现安全筛选器谓词的示例。我们在根表上应用了安全规则,并希望将这些规则应用于细节/子表。例如,如果一个销售代表创建了一个由许多装运组成的订单,其中包含许多项目,我们不希望另一个销售代表查询这些项目Tsql 如何在SQL Server 2016中对明细表实现安全筛选器谓词,tsql,sql-server-2016,Tsql,Sql Server 2016,下面是我们如何在SQL Server 2016中实现安全筛选器谓词的示例。我们在根表上应用了安全规则,并希望将这些规则应用于细节/子表。例如,如果一个销售代表创建了一个由许多装运组成的订单,其中包含许多项目,我们不希望另一个销售代表查询这些项目 USE [TestSecurity2016b] GO /****** Object: Table [dbo].[OrderDetails] Script Date: 2017-01-02 09:14:49 ******/ SET ANSI_NU
USE [TestSecurity2016b]
GO
/****** Object: Table [dbo].[OrderDetails] Script Date: 2017-01-02 09:14:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Orders]
(
[ID] [int] NOT NULL,
[SalesRep] [sysname] NOT NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[OrderShipments]
(
[ID] [int] NOT NULL,
[FK_OrderID] [int] NOT NULL,
[TrackingNumber] [varchar](25) NULL,
[ShippedOn] [Date] NULL,
) ON [PRIMARY]
CREATE TABLE [dbo].[OrderShipmentItems]
(
[ID] [int] NOT NULL,
[FK_OrderShipmentID] [int] NOT NULL,
[Product] [varchar](25) NOT NULL,
[Quantity] [int] NOT NULL,
) ON [PRIMARY]
GO
insert dbo.Orders values
(1, 'SalesRep1'),
(2, 'SalesRep2');
insert dbo.[OrderShipments] values
(1, 1, '1234', '2016-12-25'),
(2, 1, '4321', '2016-12-26'),
(3, 2, '5678', '2017-01-01');
insert dbo.[OrderShipmentItems] values
(1, 1, 'Benq w1070', 1),
(2, 1, '#8 Stainless bolts', 4),
(3, 2, 'HP x360 Laptop', 1),
(4, 3, 'Nintendo NES', 1),
(5, 3, 'Intellivision', 1),
(6, 3, 'Coleco', 1);
GO
create user Manager without login;
create user SalesRep1 without login;
create user SalesRep2 without login;
GO
grant select on dbo.Orders to Manager;
grant select on dbo.[OrderShipments] to Manager;
grant select on dbo.[OrderShipmentItems] to Manager;
grant select on dbo.Orders to SalesRep1;
grant select on dbo.[OrderShipments] to SalesRep1;
grant select on dbo.[OrderShipmentItems] to SalesRep1;
grant select on dbo.Orders to SalesRep2;
grant select on dbo.[OrderShipments] to SalesRep2;
grant select on dbo.[OrderShipmentItems] to SalesRep2;
GO
create function dbo.fn_orderfilter_predicate(@SalesRep as sysname)
returns table
with schemabinding
as
return select 1 as result
where @SalesRep = user_name() or user_name() = 'Manager';
GO
create function dbo.fn_ordershipmentsfilter_predicate(@FK_OrderID as int)
returns table
with schemabinding
as
return select 1 as result
where @FK_OrderID in (select ID as OrdersID from dbo.Orders where SalesRep = user_name() or user_name() = 'Manager')
GO
create function dbo.fn_ordershipmentitemsfilter_predicate(@FK_OrderShipmentID as int)
returns table
with schemabinding
as
return select 1 as result
where @FK_OrderShipmentID in
(
SELECT OrderShipments.ID AS OrderShipmentID
FROM dbo.Orders INNER JOIN
dbo.OrderShipments ON Orders.ID = OrderShipments.FK_OrderID
WHERE (Orders.SalesRep = USER_NAME() OR USER_NAME() = 'Manager')
AND (OrderShipments.ID = @FK_OrderShipmentID)
)
GO
create security policy OrdersFilter
add filter predicate dbo.fn_orderfilter_predicate(SalesRep)
on dbo.Orders
with (state = on);
GO
create security policy OrderShipmentsFilter
add filter predicate dbo.fn_ordershipmentsfilter_predicate(FK_OrderID)
on dbo.OrderShipments
with (state = on);
GO
create security policy OrderShipmentItemsFilter
add filter predicate dbo.fn_ordershipmentitemsfilter_predicate(FK_OrderShipmentID)
on dbo.OrderShipmentItems
with (state = on);
GO
execute as user = 'SalesRep1';
select * from dbo.Orders;
select * from dbo.OrderShipments;
select * from dbo.OrderShipmentItems;
revert;
GO
execute as user = 'SalesRep2';
select * from dbo.Orders;
select * from dbo.OrderShipments;
select * from dbo.OrderShipmentItems;
revert;
GO
execute as user = 'Manager';
select * from dbo.Orders;
select * from dbo.OrderShipments;
select * from dbo.OrderShipmentItems;
revert;
GO
这带来了一些问题:
-随着子级的增加,谓词的复杂性增加
-更改根表上的安全规则需要更改所有子表的规则
有没有办法解决这些问题
谢谢您可以在视图中使用handle row policy(例如与schema policy结合使用),但如果类型越多,复杂性就会增加。是否有办法让安全谓词在与初始查询相同的上下文中运行?查询/连接谓词中的其他表似乎不会被它们各自的安全谓词过滤。通过db引擎处理安全性(行策略)是不常见的。这是应用程序的任务。您可以创建具有权限/角色的表,动态处理数据连接和权限,或者创建过程集合,添加执行过程的权限,并在过程内进行选择和筛选。