SQL Server 用角色(Role)管理數據庫權限


 

當數據庫越來越多,連接到數據庫的應用程序,服務器,賬號越來越多的時候,為了既能達到滿足賬號操作數據權限需求,又不擴大其操作權限,保證數據庫的安全性,有時候需要用角色來參與到權限管理中,通過角色做一個權限與訪問用不之前的映射,可以更加方便地管理權限。

USE master
GO
--創建一個用戶
CREATE LOGIN ReadUser WITH PASSWORD ='123qwe!@#',DEFAULT_DATABASE=DBTest


USE DBTest
GO
 --創建用戶,指定到上面
CREATE USER ReadUser FOR LOGIN ReadUser WITH DEFAULT_SCHEMA = dbo

 

用SETUSER 切換到上面建的ReadUser賬號下面,通過print Session_user發現已經切換到了ReadUser,以ReadUser的身份執行一個查詢,

此時提示ReadUser沒有DetailTable的SELECT 權限

以管理員身份授權給ReadUser查詢dbo.DetailTable表的權限

再次以ReadUser的身份執行上述查詢,這次發現可以正常執行了

如果允許ReadUser這個賬號對當前庫多張表都要有查詢的全新,就要將GRANT SELECT ON TableName重復N次,
那么問題就來了,如果此時需要再建一個同樣權限的用戶,ReadUser2,授予同樣的權限,又要重復N此GRANT操作?

此時就需要借助角色這一數據庫對象來管理權限,將User加入到某一個角色中,來避免每次新增一個User都要執行一遍授權操作。

 

首先用管理員權限創建一個角色ReadRole

 

然后依次執行如下操作,將之前授權給ReadUser的權限給Revoke掉,

1,新建一個名稱為ReadRole的角色

2,將多張表的查詢權限授予ReadRole這一角色

3,將User加入到這個角色中

執行完成之后,我們在來嘗試UserRead這個角色的權限,可以發現:角色有的權限,ReadUser也都有了

 

如果此時再新建一個ReadUser2

此時切換到ReadUser2的身份下,發現ReadUser2也具備了ReadRole這個自定義角色的權限

 

上述的ReadRole是自定義的角色,上面給他授權的是當前數據庫中的部分表的SELECT權限
如果需要全庫的所有表的SELECT權限,就可以借助DataBase Role來實現了,將用戶加入到DataBase級別的db_dataReader這個角色中
如下截圖

DataBase級別的角色作用范圍是整個DB的,比如db_datareader,db_datawriter都是作用在數據庫所有的對象
對於這種范圍比較大而不適合使用的場景,就可以采用類似上述自定義角色,通過給角色授予指定范圍內的權限的方式來實現用戶權限管理

 

角色不僅可以在表上做權限控制和管理,也可以管理視圖(查詢),存儲過程(執行),函數(查詢),Sequence(Sequence是Update)等對象上的操作權限,通過授權給角色權限,把某一列用戶加入到某一個角色中,用角色來管理用戶和數據庫對象之間的權限管理,可以做到更加統一地管理權限。

 

最后,附上兩個腳本

1.查詢某個角色擁有哪些權限

--查詢某個角色擁有的權限
select USER_NAME(p.grantee_principal_id) AS principal_name,
            dp.principal_id,
            dp.type_desc AS principal_type_desc,
            p.class_desc,
            OBJECT_NAME(p.major_id) AS object_name,
            p.permission_name,
            p.state_desc AS permission_state_desc
from sys.database_permissions p 
            INNER JOIN sys.database_principals dp on  p.grantee_principal_id = dp.principal_id 
where USER_NAME(p.grantee_principal_id) =  'ReadRole' --角色名稱

2.查詢某個User有哪些角色的權限(User屬於哪一個(多個)角色)

--某個User有哪些角色的權限(User屬於哪一個(多個)角色)
SELECT u.name, r.name
FROM sys.database_role_members AS m
        INNER JOIN sys.database_principals AS r ON m.role_principal_id = r.principal_id
        INNER JOIN sys.database_principals AS u ON u.principal_id = m.member_principal_id
WHERE u.name = 'ReadUser'; --UserName

3.查詢某個賬號有哪些權限,直接授權給賬號的,而不是通過角色繼承來的

--查詢某個賬號有哪些權限,直接授權給賬號的,而不是通過角色繼承來的
select USER_NAME(p.grantee_principal_id) AS principal_name,
        p.grantee_principal_id,
        dp.principal_id,
        dp.type_desc AS principal_type_desc,
        p.class_desc,
        OBJECT_NAME(p.major_id) AS object_name,
        p.permission_name,
        p.state_desc AS permission_state_desc
from sys.database_permissions p 
        INNER JOIN sys.database_principals dp on  p.grantee_principal_id = dp.principal_id 
where USER_NAME(p.grantee_principal_id) = 'ReadUser'

 

4.查詢一個UserName擁有的所有權限(通過角色集成的權限和自身具備的權限)

--查詢一個UserName擁有的角色以及角色擁有的操作對象
DECLARE @login_name varchar(100) = 'XXX'

;WITH LoginName
AS
(
    SELECT  u.name            AS LoginName,
            r.name          AS RoleName,
        role_principal_id   AS PrincipalId
    FROM sys.database_role_members AS m
    INNER JOIN sys.database_principals AS r ON r.principal_id = m.role_principal_id
    INNER JOIN sys.database_principals AS u ON u.principal_id = m.member_principal_id
),
UserPermission
AS
(
    select USER_NAME(p.grantee_principal_id)   AS principal_name,
            dp.principal_id                    AS principal_id,
            dp.type_desc                       AS principal_type_desc,
            p.class_desc                       AS class_desc,
            OBJECT_NAME(p.major_id)            AS object_name,
            p.permission_name                  AS permission_name,
            p.state_desc                       AS permission_state_desc
    from sys.database_permissions p
    INNER JOIN sys.database_principals dp on  p.grantee_principal_id = dp.principal_id
)
SELECT * FROM
(

    --通過角色獲取的權限對象
    SELECT  u.LoginName,
            u.RoleName,
            p.principal_type_desc,
            p.class_desc,
            p.permission_name,
            p.object_name,
            p.permission_state_desc
    FROM LoginName u left join UserPermission p on p.principal_name = u.RoleName
    WHERE u.LoginName = @login_name
      
    UNION ALL
    --直接授權給賬號的權限對象
    select      @login_name             AS LoginName,
                ''                      AS RoleName,
                dp.type_desc            AS principal_type_desc,
                p.class_desc            AS class_desc,
                p.permission_name       AS permission_name,
                OBJECT_NAME(p.major_id) AS object_name,
                p.state_desc            AS permission_state_desc
    from sys.database_permissions p
                INNER JOIN sys.database_principals dp on  p.grantee_principal_id = dp.principal_id
    where USER_NAME(p.grantee_principal_id) = @login_name

    UNION ALL
    --固定服務器角色的權限
    SELECT      r.name            ,
                cast(r.principal_id as varchar(10))    ,
                r.type_desc,
                null as class_desc,
                null as object_name,
                p2.name as permission_name,
                null as permission_state_desc
    FROM sys.server_principals r
    INNER JOIN sys.server_role_members m ON r.principal_id = m.member_principal_id
    INNER JOIN sys.server_principals p1 ON p1.principal_id = m.member_principal_id
    INNER JOIN sys.server_principals p2 ON p2.principal_id = m.role_principal_id  
    WHERE r.name = @login_name
)t

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM