Lia*_*amB 12 sql-server row-level-security
我有一个这样结构的表(简化)
Name, EMail, LastLoggedInAt
Run Code Online (Sandbox Code Playgroud)
我在 SQL Server (RemoteUser) 中有一个用户,该用户应该只能看到 LastLoggdInAt 字段不为空的数据(通过选择查询)。
看起来我可以做到这一点?是否可以?
Han*_*non 33
SQL Server 安全模型允许您授予对视图的访问权限,而无需授予对基础表的访问权限。
由于示例代码是展示概念的好方法,请考虑以下内容,以及一个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
Run Code Online (Sandbox Code Playgroud)
我们将创建一个登录名和一个用户,然后为该用户分配从视图中选择行的权限,而没有任何查看表本身的权限。
CREATE LOGIN RemoteUser
WITH PASSWORD = '2q1345lkjsadfgsa0(*';
CREATE USER RemoteUser
FOR LOGIN RemoteUser
WITH DEFAULT_SCHEMA = dbo;
GRANT SELECT ON dbo.LoginDetailsView TO RemoteUser;
Run Code Online (Sandbox Code Playgroud)
现在,我们将插入两个测试行:
INSERT INTO dbo.LoginDetails(Username, EmailAddress, LastLoggedInAt)
VALUES ('user x', 'x@y.com', NULL)
, ('user y', 'y@y.com', GETDATE());
Run Code Online (Sandbox Code Playgroud)
这将测试安全模型。第一条SELECT语句成功,因为它是从视图中进行选择,而第二条SELECT语句失败,因为用户没有直接访问表的权限。
EXECUTE AS LOGIN = 'RemoteUser';
SELECT *
FROM dbo.LoginDetailsView;
Run Code Online (Sandbox Code Playgroud)
?????????????????????????????????????????????????????? ??? ? 用户名 ?电子邮件地址 ?LastLoggedInAt ? ?????????????????????????????????????????????????????? ??? ? 用户 ? y@y.com ?2018-02-15 07:36:54.490? ?????????????????????????????????????????????????????? ???
SELECT *
FROM dbo.LoginDetails;
REVERT
Run Code Online (Sandbox Code Playgroud)
请注意视图中的结果排除了LastLoggedInAt值所在的行NULL,如您的问题所要求的那样。
SELECT针对基础表的第二条语句返回错误:
消息 229,级别 14,状态 5,第 28 行
对象“LoginDetails”、数据库“tempdb”、架构“dbo”的 SELECT 权限被拒绝。
清理:
DROP USER RemoteUser;
DROP LOGIN RemoteUser;
DROP VIEW dbo.LoginDetailsView;
DROP TABLE dbo.LoginDetails;
Run Code Online (Sandbox Code Playgroud)
或者,如果您有 SQL Server 2016 或更高版本,您可以使用行级安全谓词来防止某些用户看到具有 NULLLastLoggedInAt值的行。行级安全性的 Microsoft Docs在这里。
首先,我们创建表、登录名、该登录名的用户,并授予对该表的访问权限:
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;
Run Code Online (Sandbox Code Playgroud)
接下来,我们插入几个示例行。一行具有 null LastLoggedInAt,另一行具有该列的非空值。
INSERT INTO dbo.LoginDetails(Username, EmailAddress, LastLoggedInAt)
VALUES ('user x', 'x@y.com', NULL)
, ('user y', 'y@y.com', GETDATE());
Run Code Online (Sandbox Code Playgroud)
在这里,我们创建了一个模式绑定的表值函数,它根据传递给函数的@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
Run Code Online (Sandbox Code Playgroud)
这是从SELECT针对dbo.LoginDetails表运行的语句中消除行的安全过滤器:
CREATE SECURITY POLICY LoginDetailsRemoteUserPolicy
ADD FILTER PREDICATE dbo.fn_LoginDetailsRemoteUserPredicate(LastLoggedInAt, USER_NAME())
ON dbo.LoginDetails
WITH (STATE=ON);
Run Code Online (Sandbox Code Playgroud)
上面的过滤器dbo.fn_LoginDetailsRemoteUserPredicate通过传入当前用户的名称以及表中LastLoggedInAt列的每一行的值来使用该函数dbo.LoginDetails。
如果我们以普通用户的身份查询表:
SELECT *
FROM dbo.LoginDetails
Run Code Online (Sandbox Code Playgroud)
我们看到所有行:
?????????????????????????????????????????????????????? ??? ? 用户名 ?电子邮件地址 ?LastLoggedInAt ? ?????????????????????????????????????????????????????? ??? ? 用户 x ? x@y.com ? 空值 ? ? 用户 ? y@y.com ?2018-02-15 13:53:42.577 ? ?????????????????????????????????????????????????????? ???
但是,如果我们测试为RemoteUser:
EXECUTE AS LOGIN = 'RemoteUser';
SELECT *
FROM dbo.LoginDetails
REVERT
Run Code Online (Sandbox Code Playgroud)
我们只看到“有效”行:
?????????????????????????????????????????????????????? ??? ? 用户名 ?电子邮件地址 ?LastLoggedInAt ? ?????????????????????????????????????????????????????? ??? ? 用户 ? y@y.com ?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;
Run Code Online (Sandbox Code Playgroud)
请注意,以这种方式将函数模式绑定到表确实无法在不首先删除过滤谓词和dbo.fn_LoginDetailsRemoteUserPredicate函数的情况下修改表的定义。
| 归档时间: |
|
| 查看次数: |
982 次 |
| 最近记录: |