我的Windows服务需要SQL Server 2005数据库的执行权限。在启动时,我检查是否可以连接到数据库并停止服务,如果我不能。我还想检查是否可以使用该连接执行存储过程。有没有办法在没有实际尝试执行sproc并查看异常的情况下执行此操作?
答案 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数据库,可以得到以下结果:
注意您可以配置步骤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并对其运行查询,以确定您登录的帐户具有哪些权限。这会因数据库而异。