簡體   English   中英

如何確定我是否對數據庫具有執行權限?

[英]How do I determine if I have execute permissions on a DB programatically?

我有一個Windows服務,該服務要求對SQL Server 2005 DB具有執行權限。 在啟動時,我檢查是否可以連接到數據庫並在無法連接時停止該服務。 我還想檢查一下是否可以使用該連接執行存儲過程。 有沒有一種方法可以執行此操作而無需實際嘗試執行sproc並查看異常(如果發生)?

SQL 2005及HAS_PERM_BY_NAME ,您可以使用HAS_PERM_BY_NAME檢查任何權限:

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

您可以運行如下查詢:

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

該答案的第一部分顯示了如何在T-SQL中檢查權限,第二部分給出了一個如何在Entity Framework中使用它的示例(請注意,EF版本之間存在差異-給出的示例為EF 4,但是可以輕松更改為較新版本):


第一部分(SQL):

我正在使用以下T-SQL腳本檢查權限。 它首先檢查您是否具有任何權限,然后檢查SP的執行權限,最后選擇表的權限。 請參閱鏈接以獲取更多信息。

-- 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;

羅斯文數據庫為例,這將為您提供以下結果:

Query_results

請注意 ,您可以配置在步驟2中考慮的模式。如果不需要檢查一組有限的模式,則只需注釋掉insert into @SchemaList語句中的where子句即可獲取所有模式。


第二部分(實體框架):

在本節中,我想向您展示如何將結果獲取到Entity Framework中。 假設您要使用LINQ查詢中的任何表之前檢查是否擁有任何權限。 看一下這個例子(為簡單起見,我已經在LinqPad中完成了它,請在運行它之前通過F4添加System.Data.Entity.dll及其名稱空間):

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

我認為您已經明白了,並嘗試了各種可能性:請記住,EF需要訪問您要映射到的所有數據庫表,存儲過程等-您可以在訪問它們之前使用上面的代碼進行檢查。 不幸的是,目前沒有更簡單的方法可以做到這一點。

您將必須具有訪問數據庫的DataDictionary的權限,並對它運行查詢以確定登錄帳戶所擁有的權限。 這將因數據庫而異。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM