【发布时间】:2021-10-26 10:46:54
【问题描述】:
我有一个存储过程 z 读取表 A 并写入表 B + C 必须在 B 和 C 之间过程不停止(金融交易,比如你不能在不从 C 中获取的情况下添加到 B)
为了避免这种情况,并且因为运行该过程的用户不应该对 A、B 或 C 有任何权限,并且有时服务器连接可能会断开,我构建了以下内容:
ALTER PROCEDURE [INV].[Z]
AS
BEGIN
DECLARE @CanAcessAllTables int =
(SELECT IIF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME in (A, B, C) ) = 3, 1, 0))
IF @CanAcessAllTables <> 1
RAISERROR('Looks like we either can not connect to the server or you lack some aditional permissions', 16, 16)
ELSE
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO [INV].[B] ( col1, col2) VALUES (1, 2)
INSERT INTO [INV].[C] ( col3, col4) VALUES (1, 2)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT 'Please report the following table for support:'
SELECT
ERROR_MESSAGE() as ErrorMessage,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_LINE() as ErrorLine,
ERROR_STATE() as ErrorState,
ERROR_SEVERITY() as ErrorSeverity,
ERROR_NUMBER() as ErrorNumber
END CATCH
END
GO
我的想法是 sp 会检查他(sp)是否可以访问所有 3 个表,而不是检查运行 Z 的用户是否可以访问所有 3 个表,自然用户没有对所有 3 个和结果的权限在“看起来我们要么无法连接到服务器,要么您缺少一些额外的权限”错误 这有点讽刺,因为通过消除该引发错误,sp 将运行。
那么我的问题是,我应该用什么来确保在任何情况下 B 和 C 一起运行或根本不运行(即使有人将表 B 重命名为 B_1 或撤销 sp 对 C 的写权限)
【问题讨论】:
-
您的顾虑纵横交错。如果您使用 RBAC 并且需要与表相同的角色来访问存储过程,则 AuthX 可以由 SQL Server 直接处理。
-
" '请报告下表以获得支持:'" INSERT INTO 是自找麻烦。 在
INSERT语句中始终使用明确的列名 -
如果所有权链未中断,则不会检查 proc 使用的表的权限(如这里所示)。
-
另外,您的 human 用户真的都有不同的 SQL
LOGIN和USER对象吗?这些天很少发生这种事情...... -
只需重新抛出错误,或者,抛出一个通用但用户友好的错误并在某处记录实际错误。并且不要使用 SELECT 生成包含“友好”消息供应用程序处理的结果集。您的应用程序应该足够智能以直接提供(如果服务或批处理正在执行此操作,则不提供)。您将自己的假设推入您的程序逻辑中。
标签: sql-server tsql security stored-procedures