如何以编程方式确定我是否对DB具有执行权限?

时间:2009-10-13 19:53:28

标签: c# sql stored-procedures permissions

我的Windows服务需要SQL Server 2005数据库的执行权限。在启动时,我检查是否可以连接到数据库并停止服务,如果我不能。我还想检查是否可以使用该连接执行存储过程。有没有办法在没有实际尝试执行sproc并查看异常的情况下执行此操作?

4 个答案:

答案 0 :(得分:11)

SQL 2005以及您可以使用HAS_PERM_BY_NAME检查任何权限:

SELECT HAS_PERMS_BY_NAME('sp_foo', 'OBJECT', 'EXECUTE');

答案 1 :(得分:3)

你可以运行这样的查询:

SELECT
    o.NAME,COALESCE(p.state_desc,'?permission_command?')+' '+COALESCE(p.permission_name,'?permission_name?')+' ON ['+SCHEMA_NAME(o.schema_id)+'].['+COALESCE(o.Name,'?object_name?')+'] TO ['+COALESCE(dp.Name,'?principal_name?')+']' COLLATE SQL_Latin1_General_CP1_CI_AS AS GrantCommand
    FROM sys.all_objects                          o
        INNER JOIN sys.database_permissions       p ON o.OBJECT_ID=p.major_id
        LEFT OUTER JOIN sys.database_principals  dp ON p.grantee_principal_id = dp.principal_id
    where p.state_desc='GRANT' AND p.permission_name='EXECUTE'
        AND o.NAME='YourProcedureName'
        AND dp.Name='YourSecurityName'

...并删除grant命令的花哨格式,它只用于参考

这些也很好......

SELECT * FROM fn_my_permissions('YourTable', 'OBJECT') 
SELECT * FROM fn_my_permissions('YourProcedure', 'OBJECT') 
SELECT * FROM fn_my_permissions (NULL, 'DATABASE')
SELECT * FROM fn_my_permissions(NULL, 'SERVER')

要查看其他人拥有的权限,您可以执行以下操作:

EXECUTE AS user = 'loginToTest'
GO
PRINT 'SELECT permissions on tables:'
SELECT
    HAS_PERMS_BY_NAME(    QUOTENAME(SCHEMA_NAME(schema_id))+'.' + QUOTENAME(name)
                          ,'OBJECT','SELECT'
                     ) AS have_select
        , * 
    FROM sys.tables;

PRINT 'EXECUTE permissions on stored procedures:'
SELECT
    HAS_PERMS_BY_NAME(    QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name)
        ,'OBJECT', 'EXECUTE') AS have_execute
        , * 
    FROM sys.procedures;
GO
REVERT;
GO

答案 2 :(得分:1)

本答案的第一部分显示了如何检查 T-SQL 中的权限,第二部分给出了如何在实体框架中使用此功能的示例(注意EF版本之间存在差异 - 给出的示例是EF 4,但可以轻松更改为更新版本):


第一部分(SQL):

我使用以下 T-SQL 脚本来检查权限。它首先检查您是否拥有任何权限,然后检查SP的执行权限,最后选择表的权限。请参阅this链接以获取更多信息。

-- 1. Do I have any permissions?
SELECT HAS_PERMS_BY_NAME(db_name(), 'DATABASE', 'ANY') DoIHaveAnyRights;

-- 2. create list of schemas
declare @SchemaList table (schema_id int, name nvarchar(max));

PRINT 'Schemas regarded:'

insert into @SchemaList
select distinct schema_id, name FROM sys.schemas
where name in ('dbo') -- enter the schemas you like to check comma-separated

SELECT s.name, s.schema_id FROM sys.schemas s
join @SchemaList sl on s.schema_id=sl.schema_id

-- 3. check execute permissions
PRINT 'EXECUTE permissions on stored procedures:'
SELECT 
    HAS_PERMS_BY_NAME(QUOTENAME(SCHEMA_NAME(t.schema_id)) + '.' + QUOTENAME(t.name)
        ,'OBJECT', 'EXECUTE') AS [have execute]
        ,'['+s.name +'].['+ t.name+']' as [object]
        --, * 
    FROM sys.procedures t
    join @SchemaList s on t.schema_id=s.schema_id
order by s.name, t.name;

-- 4. check select permissions
PRINT 'SELECT permissions on tables:'
SELECT 
    HAS_PERMS_BY_NAME(QUOTENAME(SCHEMA_NAME(t.schema_id))+'.' + QUOTENAME(t.name)
        ,'OBJECT','SELECT') AS [have select]
        ,'['+s.name +'].['+ t.name+']' as [object]
        --, * 
    FROM sys.tables t
    join @SchemaList s on t.schema_id=s.schema_id
order by s.name, t.name;

例如,使用 Northwind数据库,可以得到以下结果:

Query_results

注意您可以配置步骤2中考虑的模式。如果您不需要检查有限的模式集,则只需注释掉where子句中的insert into @SchemaList子句获取所有模式的System.Data.Entity.dll语句。


第二部分(实体框架):

在本节中,我想向您展示如何将结果导入Entity Framework。 假设您想要使用LINQ查询中的任何表检查是否拥有之前之前的任何权利。看一下这个例子(为简单起见,我已经在LinqPad中完成了它,请在运行之前通过F4添加void Main() { var dc=this; var sql="SELECT TOP 1 " + "HAS_PERMS_BY_NAME(db_name(), 'DATABASE', 'ANY') DoIHaveAnyRights;"; var result=dc.ExecuteStoreQuery<Rights>(sql); if (result1.DoIHaveAnyRights==1) { Console.WriteLine("OK"); // ok } else { // no rights: Show error etc. Console.WriteLine("No rights"); // ok } } public class Rights { public Int32 DoIHaveAnyRights { get; set; } } 及其名称空间):

var sql="select top 1 case when cnt.NoRightsCount=0 then 1 else 0 end "
+"as DoIHaveAnyRights "
+"from (SELECT count(1) NoRightsCount FROM sys.procedures t "
+"where HAS_PERMS_BY_NAME("
+"QUOTENAME(SCHEMA_NAME(t.schema_id)) + '.' + QUOTENAME(t.name)"
+",'OBJECT', 'EXECUTE')<>1) cnt";

同样,你可以使用我答案第一部分的查询,例如:

result1.DoIHaveAnyRights!=1

此查询将检查数据库中是否存在您无权执行的存储过程 - 在这种情况下,返回值为{{1}}。

我认为你明白这个想法,玩弄可能性:请记住,EF需要访问您要映射到的所有数据库表,存储过程等 - 您可以使用上面的代码进行检查你访问它们。不幸的是,目前没有更简单的方法来做到这一点。

答案 3 :(得分:0)

您必须有权访问数据库的DataDictionary并对其运行查询,以确定您登录的帐户具有哪些权限。这会因数据库而异。