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的身份執行上述查詢,此次發現能夠正常執行了spa

若是容許ReadUser這個帳號對當前庫多張表都要有查詢的全新,就要將GRANT SELECT ON TableName重複N次,
那麼問題就來了,若是此時須要再建一個一樣權限的用戶,ReadUser2,授予一樣的權限,又要重複N此GRANT操做?code

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

 

首先用管理員權限建立一個角色ReadRole對象

 

而後依次執行以下操做,將以前受權給ReadUser的權限給Revoke掉,blog

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
相關文章
相關標籤/搜索