Sql server - 使用readonly权限执行存储过程

时间:2017-07-13 15:11:56

标签: c# sql-server

首先,我说我不具备sql server安全性方面的经验。我可能有任何错误,请告诉我。

我有一个应用程序,用户可以在sql server数据库中输入要执行的sql语句。语句只能返回数据,不能执行任何DML或DDL操作。目前,输入经过验证,只允许编写SELECT语句。但现在是一个要求允许执行存储过程,但只有那些只读取数据。也可以帮助列出这些SP以显示一种智能感知。

我想创建一个只有db_datareader权限的用户,并以该用户身份执行该语句。但是要执行存储过程,我必须向用户授予执行权限,并且Ownership Chaining,可能不会检查权限。我还没弄清楚如何解决这个问题。

我还想过只允许执行在只具有读取权限的特定数据库模式中创建的存储过程。这样我就可以轻松列出SP。我不知道这是否可能。

2 个答案:

答案 0 :(得分:3)

  

但是要执行存储过程,我必须向用户授予执行权限

这应该通过创建没有登录的用户并且仅授予对该登录的选择来工作。这使用EXECUTE作为子句。您需要EXECUTE作为创建或调用此模块的权限,但执行上下文将是user1,一旦您是在只有选择权限的模块中

create user user1 without login

grant select to user1

alter proc usp_test
@sql nvarchar(max)
with execute as 'user1'

as
begin


exec sp_Executesql @sql

end


create table dbo.test
(
id int
)

insert into test
select 1
go 10

exec usp_test N'select * from test' --works
exec usp_test N'insert into test values(1)' --fails with below error
  

Msg 229,Level 14,State 5,Line 28   INSERT权限在对象'test',数据库'master',schema'dbo'上被拒绝。

答案 1 :(得分:-1)

经过一些挖掘和使用@TheGameiswar的答案,我带来了这个解决方案

1-创建“只读”用户

Create user user_reader without login

2-打破所有权链接我创建了一个新的数据库模式,其中user_reader为所有者

Create schema reader

ALTER AUTHORIZATION ON Schema::reader TO user_reader

3-授予对user_reader的选择权限

GRANT SELECT TO user_reader

4-仅在读者架构中授予对user_reader的执行权限。在其他模式中,存储过程可能与表具有相同的所有者,并且不会检查user_reader的权限,因为所有权链将是不间断的。

GRANT EXECUTE ON Schema::reader TO user_reader

5-在user_reader的上下文中执行用户编写的每个sql语句。要实现此目的,请始终在“execute as user ='user_reader'”

之前添加
public override DataTable ExecuteQuery(string query)
{
    SqlConnection connection = new SqlConnection(ConnectionString);

    StringBuilder readOnlyQuery = new StringBuilder();
    readOnlyQuery .AppendLine("execute as user = 'user_reader';");      
    readOnlyQuery .AppendLine(query);
    query = readOnlyQuery .ToString();

    SqlCommand command = new SqlCommand(query, connection);

    ...Execute the command
}

FOR TESTING

CREATE TABLE [dbo].[TestTable](
    [TestField] [int] NOT NULL
)

GO
CREATE PROCEDURE USP_INSERT
    @input int
AS
BEGIN
    INSERT INTO TestTable VALUES (@input)
END

GO

CREATE PROCEDURE reader.USP_READ
AS
BEGIN
    SELECT * FROM TestTable
END
GO

CREATE PROCEDURE reader.USP_INSERT
    @input int
AS
BEGIN
    INSERT INTO TestTable VALUES (@input)
END

<强>测试

insert into TestTable VALUES (2)
  

对象'TestTable',数据库上的INSERT权限被拒绝   '测试',架构'dbo'。

select * from TestTable
  

exec usp_read
  

对象'USP_READ',数据库上的EXECUTE权限被拒绝   '测试',架构'dbo'。

exec usp_insert 1
  

对象'USP_INSERT',数据库上的EXECUTE权限被拒绝   '测试',架构'dbo'。

exec reader.usp_insert 1
  

对象'TestTable',数据库上的INSERT权限被拒绝   '测试',架构'dbo'。

exec reader.usp_read
  

我们还可以列出阅读器架构

中的所有存储过程
select name
from sys.procedures
where SCHEMA_NAME(schema_id) = 'reader'

此解决方案符合我的要求,但对其他情况可能还不够。