我有一个应用程序,用户可以在其中输入要在 sql server 数据库中执行的 sql 语句。这些语句只能返回数据,不能执行任何 DML 或 DDL 操作。目前输入被验证只允许编写 SELECT 语句。但现在要求允许执行存储过程,但只允许那些只读取数据的过程。也将有助于列出这些 SP 以显示一种智能感知。
我想创建一个只有 db_datareader 权限的用户并以此用户身份执行语句。但是要执行存储过程,我必须向用户授予 Execute 权限,并且因为Ownership Chaining,可能不会检查权限。我还没有想出如何解决这个问题。
我还认为只允许执行在只有读取权限的特定数据库模式中创建的存储过程。同样,我可以通过这种方式轻松列出 SP。我不知道这是否可能。
经过一番挖掘和使用 @TheGameiswar 答案后,我提出了这个解决方案
\n\n1-创建一个“只读”用户
\n\nCreate user user_reader without login\nRun Code Online (Sandbox Code Playgroud)\n\n2-为了打破所有权链,我创建了一个新的数据库模式,其中 user_reader 作为所有者
\n\nCreate schema reader\n\nALTER AUTHORIZATION ON Schema::reader TO user_reader\nRun Code Online (Sandbox Code Playgroud)\n\n3-授予user_reader选择权限
\n\nGRANT SELECT TO user_reader\nRun Code Online (Sandbox Code Playgroud)\n\n4- 授予 user_reader 执行权限,仅在阅读器模式中。在其他模式中,存储过程可能与表具有相同的所有者,并且不会检查 user_reader 的权限,因为所有权链不会中断。
\n\nGRANT EXECUTE ON Schema::reader TO user_reader\nRun Code Online (Sandbox Code Playgroud)\n\n5-在user_reader上下文中执行用户编写的每一条sql语句。要实现此目的,请始终在前面加上“execute as user = \'user_reader\'”
\n\npublic override DataTable ExecuteQuery(string query)\n{\n SqlConnection connection = new SqlConnection(ConnectionString);\n\n StringBuilder readOnlyQuery = new StringBuilder();\n readOnlyQuery .AppendLine("execute as user = \'user_reader\';"); \n readOnlyQuery .AppendLine(query);\n query = readOnlyQuery .ToString();\n\n SqlCommand command = new SqlCommand(query, connection);\n\n ...Execute the command\n}\nRun Code Online (Sandbox Code Playgroud)\n\n供测试用
\n\nCREATE TABLE [dbo].[TestTable](\n [TestField] [int] NOT NULL\n)\n\nGO\nCREATE PROCEDURE USP_INSERT\n @input int\nAS\nBEGIN\n INSERT INTO TestTable VALUES (@input)\nEND\n\nGO\n\nCREATE PROCEDURE reader.USP_READ\nAS\nBEGIN\n SELECT * FROM TestTable\nEND\nGO\n\nCREATE PROCEDURE reader.USP_INSERT\n @input int\nAS\nBEGIN\n INSERT INTO TestTable VALUES (@input)\nEND\nRun Code Online (Sandbox Code Playgroud)\n\n测试:
\n\ninsert into TestTable VALUES (2)\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n对对象 \'TestTable\'、数据库\n \'Test\'、架构 \'dbo\' 的 INSERT 权限被拒绝。
\n
select * from TestTable\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n好的
\n
exec usp_read\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n对对象“USP_READ”、数据库“Test”、架构“dbo”的 EXECUTE 权限被拒绝。
\n
exec usp_insert 1\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n对对象“USP_INSERT”、数据库“Test”、架构“dbo”的 EXECUTE 权限被拒绝。
\n
exec reader.usp_insert 1\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n对对象 \'TestTable\'、数据库\n \'Test\'、架构 \'dbo\' 的 INSERT 权限被拒绝。
\n
exec reader.usp_read\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n好的
\n
我们还可以列出阅读器模式中的所有存储过程
\n\nselect name\nfrom sys.procedures\nwhere SCHEMA_NAME(schema_id) = \'reader\'\nRun Code Online (Sandbox Code Playgroud)\n\n该解决方案满足我的要求,但对于其他情况可能还不够。
\n