在这种情况下,我寻求帮助来为名为“user”且列为“username”和“role”的表实现行级权限。目标是建立一个安全模型,根据分配给每个用户的角色来控制对各个行的访问。具体来说,权限应遵循以下条件:当 @username=USER_NAME() 时,role='members' 只能查看 1 行,而当 @username=USER_NAME() 时,role='admins' 可以查看自己的行,并且带有角色='成员'。对于role='ceos',他们可以查看自己的行以及role='admins'的行。
CREATE FUNCTION Security.fn_securitypredicate3
(@username AS nvarchar(50), @role AS varchar(10))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN (
SELECT 1 AS Result
FROM dbo.user
WHERE
(@username = USER_NAME() AND @role = 'members' AND username = @username)
OR
(@username = USER_NAME() AND @role = 'admins' AND (username = @username OR role = 'members'))
OR
(@username = USER_NAME() AND @role = 'ceos' AND (username = @username OR role = 'admins'))
);
当我使用admin帐户登录时,我只能看到它自己的行,而看不到role='members'的行
您似乎有点困惑:
@username
和@role
代表正在尝试查看的行,而函数中的dbo.user
代表当前登录用户的行。
因此,您需要从第二个和第三个分支中删除
@username = USER_NAME()
作为谓词,并将其余部分转移到一组 OR
谓词中。
username = @username
可以作为单个谓词提升出来。这会将函数内的查询限制为当前用户的单行,因此我们可以确定他们的角色。
CREATE OR ALTER FUNCTION Security.fn_securitypredicate3
(
@username AS nvarchar(50),
@role AS varchar(10)
)
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN
SELECT 1 AS Result
FROM dbo.[user] u
WHERE u.username = @username
AND (
@username = USER_NAME()
OR
u.role = 'admins' AND @role = 'members'
OR
u.role = 'ceos' AND @role = 'admins'
)
;