當數據庫愈來愈多,鏈接到數據庫的應用程序,服務器,帳號愈來愈多的時候,爲了既能達到知足帳號操做數據權限需求,又不擴大其操做權限,保證數據庫的安全性,有時候須要用角色來參與到權限管理中,經過角色作一個權限與訪問用不以前的映射,能夠更加方便地管理權限。數據庫
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