SQL Server 权限管理
2014-11-10 08:37 by pursuer.chen, 24214 阅读, 40 评论, 收藏, 编辑
概述
对数据库系统而言,保证数据的安全性永远都是最重要的问题之一。一个好的数据库环境,必须明确每个用户的职责,并分配其对应的权限。同时出现问题了也可以找到根源。
你是否会有这样的需求:
- 给某个用户查询所有数据库的权限
- 给某个用户只有备份数据库的权限
- 给一个用户只有指定数据库的权限
- 给一个用户只有某个表的权限
- 给一个用户只有查看某些对象(例如:视图)的权限
- 给一个用户只有执行一些存储过程的权限
目录
元素
文章可能会有些枯燥,还望耐心,相信应该有你想要的。
登入名
只有拥有了登入名才能访问实例(sql server).
角色
角色是一类权限的组合。
- 数据库角色的拥有者可以是用户也可以是数据库角色本身,管理员可以创建数据库角色,也可以勉强将数据库角色理解为一组相同权限的用户,为什么这么说呢,因为数据库角色和数据库用户不允许存在同名。
注意:不要将用户创建的数据库角色添加到固定的服务器数据库角色当中去,否则将导致固定的数据库角色的权限升级。
- 服务器角色的拥有者只有登入名,服务器角色是固定的,用户无法创建服务器角色。
注意:一般不建议给用户直接分配服务器角色,因为服务器角色是全局的,也就是说你拥有了服务器级别的权限,一般建议给用户分配数据库,然后给对应的数据库分配数据库角色权限。
用户
用户是数据库级的概念,数据库用户必须绑定具体的登入名,你也可以在新建登入名的时候绑定此登入名拥有的数据库,当你绑定登入名数据库后,数据库默认就创建了此登入名同名的数据库用户,登入名与数据库用户之间就存在关联关系,数据库用户是架构和数据库角色的拥有者,即你可以将某个架构分配给用户那么该用户就拥有了该架构所包含的对象,你也可以将某个数据库角色分配给用户,此用户就拥有该数据库角色的权限。
架构
架构是对象的拥有者,架构本身无权限,架构包含数据库对象:如表、视图、存储过程和函数等,平时最常见的默认架构dbo.,如果没指定架构默认创建数据库对象都是以dbo.开头,架构的拥有者是数据库用户、数据库角色、应用程序角色。用户创建的架构和角色只能作用于当前库。
理解了这些概念之后接下来就可以实践了,接下来我们测试的都是服务器角色选择public,只测试对数据库权限的控制。
权限分配
新建登入名
新建一个登入名person,只给登入名服务器角色分配public权限,不分配数据库
接下来用person登入实例,person用户无法访问任何数据库,由于我们未给用户分配任何数据库。
给用户分配数据库查看权限
只允许用户查看AdventureWorks2008R2数据库
此时用户可以查询所有对象,但无法修改对象。
给用户查询某个对象的权限
如果觉得给用户查看权限太大了,将da_datareader数据库角色权限回收,你会发现用户可以访问数据库,但是看不到任何对象。
只给用户查看Person.Address表
USE AdventureWorks2008R2; GRANT SELECT ON OBJECT::Person.Address TO person; --或者使用 USE AdventureWorks2008R2; GRANT SELECT ON Person.Address TO RosaQdM; GO
扩展功能
--以下都是赋予用户对表的dml权限
---授予用户person对表Person.Address的修改权限 USE AdventureWorks2008R2; GRANT UPDATE ON Person.Address TO person; GO ---授予用户person对表Person.Address的插入权限 USE AdventureWorks2008R2; GRANT INSERT ON Person.Address TO person; GO ---授予用户person对表Person.Address的删除权限 USE AdventureWorks2008R2; GRANT DELETE ON Person.Address TO person;--授予用户存储过程dbo.prc_errorlog的执行权限
GRANT EXECUTE ON dbo.prc_errorlog TO person
标量函数权限:EXECUTE、REFERENCES。
表值函数权限:DELETE、INSERT、REFERENCES、SELECT、UPDATE。
存储过程权限:EXECUTE。
表权限:DELETE、INSERT、REFERENCES、SELECT、UPDATE。
视图权限:DELETE、INSERT、REFERENCES、SELECT、UPDATE。
授予用户架构的权限
新建数据库角色db_persons
新增架构
数据库-安全性-架构
架构包含数据库对象
创建架构persons表
---创建架构persons的表 CREATE TABLE Persons.sutdent (id int not null)
你会发现用户同时有了Persons.sutdent表的查看权限,因为用户是数据库角色db_person的所有者,而db_person又是架构persons的所有者。
创建一些persons架构的视图,存储过程
---创建视图 USE AdventureWorks2008R2 GO CREATE VIEW Persons.vwsutdent AS SELECT * FROM Persons.sutdent GO USE AdventureWorks2008R2 GO ---创建存储过程 CREATE PROCEDURE Persons.SP_sutdent (@OPTION NVARCHAR(50)) AS BEGIN SET NOCOUNT ON IF @OPTION=‘Select‘ BEGIN SELECT * FROM Persons.sutdent END END
详细的GRANT功能可以查询2008r2连接丛书:
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.zh-CHS/s10de_6tsql/html/a760c16a-4d2d-43f2-be81-ae9315f38185.htm
查询权限
---登入名表 select * from master.sys.syslogins ---登入名与服务器角色关联表 select * from sys.server_role_members ---服务器角色表 select * from sys.server_principals ----查询登入名拥有的服务器角色 select SrvRole = g.name, MemberName = u.name, MemberSID = u.sid from sys.server_role_members m inner join sys.server_principals g on g.principal_id = m.role_principal_id inner join sys.server_principals u on u.principal_id = m.member_principal_id ---数据库用户表 select * from sysusers ---数据库用户表角色关联表 select * from sysmembers ---数据库角色表 select * from sys.database_principals ----查询数据库用户拥有的角色 select ta.name as username,tc.name as databaserole from sysusers ta inner join sysmembers tb on ta.uid=tb.memberuid inner join sys.database_principals tc on tb.groupuid=tc.principal_id
查询登入名与数据库用户之间的关系
--查询当前数据库用户关联的登入名 use AdventureWorks2008R2 select ta.name as loginname,tb.name as databaseusername from master.sys.syslogins ta inner join sysusers tb on ta.sid=tb.sid /*如果将当前数据库还原到另一台服务器实例上,刚好那台服务器上也存在person登入用户,你会发现二者的sid不一样, 由于sid不一样,所以登入用户不具有当前数据库的访问权限,我们要想办法将二者关联起来。 */ ---关联登入名与数据库用户(将数据库用户的sid刷成登入名的sid) use AdventureWorks2008R2 EXEC sp_change_users_login ‘Update_One‘, ‘person‘, ‘person‘ Go
查询数据库用户被授予的权限
exec sp_helprotect @username = ‘person‘
查询person数据库用户权限会发现,数据库用户拥有的权限都是前面使用GRANT赋予的权限,而后面给用户分配的架构对象不在这个里面显示,上面显示的只是被授予的权限,而架构是数据库用户所拥有的权限。
回收权限
如果安全对象是数据库,对应 BACKUP DATABASE、BACKUP LOG、CREATE DATABASE、CREATE DEFAULT、CREATE FUNCTION、CREATE PROCEDURE、CREATE RULE、CREATE TABLE 和 CREATE VIEW。
如果安全对象是标量函数,对应 EXECUTE 和 REFERENCES。
如果安全对象是表值函数,对应 DELETE、INSERT、REFERENCES、SELECT 和 UPDATE。
如果安全对象是存储过程,表示 EXECUTE。
如果安全对象是表,对应 DELETE、INSERT、REFERENCES、SELECT 和 UPDATE。
如果安全对象是视图, 对应 DELETE、INSERT、REFERENCES、SELECT 和 UPDATE。
回收dbo.prc_errorlog存储过程的执行权限
USE AdventureWorks2008R2; REVOKE EXECUTE ON dbo.prc_errorlog FROM person;
回收Person.Address表的查询,修改,删除权限
--回收修改 USE AdventureWorks2008R2; REVOKE update ON Person.Address FROM person; USE AdventureWorks2008R2; REVOKE alter ON Person.Address FROM person; --回收删除 USE AdventureWorks2008R2; REVOKE delete ON Person.Address FROM person; --回收查询 USE AdventureWorks2008R2; REVOKE select ON Person.Address FROM person;
最后剩下owner为‘.’的是数据库级的权限
最后回收数据库的权限
USE AdventureWorks2008R2; REVOKE CREATE TABLE FROM person; GO
CONNECT权限是用户访问数据库的权限,将此权限回收后用户将无法访问数据库 --USE AdventureWorks2008R2; --REVOKE CONNECT FROM person; --GO
再执行exec sp_helprotect @username = ‘person‘,就剩下action=connect的数据库访问权限
将权限回收后,数据库用户还剩下架构Persons的权限,如果还需要将该权限回收,只需要用户取消关联对应的db_person数据库角色权限。
详细的revoke权限回收请参考2008r2联机丛书:
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.zh-CHS/s10de_6tsql/html/9d31d3e7-0883-45cd-bf0e-f0361bbb0956.htm
补充
针对生产数据库服务器创建一个应用程序访问的用户最常见的是授予用户某个数据库:“查询”、“删除”、“修改”、“插入”、“执行”的权限,用SQL语句实现如下(用户:person,数据库:news):USE [master] GO ---创建登入名 CREATE LOGIN [person] WITH PASSWORD=N‘person‘, DEFAULT_DATABASE=[news], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO USE [news] GO ---在指定的数据库下创建和登入名相关联的数据库用户 CREATE USER [person] FOR LOGIN [person] GO USE [news] GO ---在指定的数据库下授予用户SELECT,DELETE,UPDATE,INSERT,EXECUTE权限。 GRANT SELECT,DELETE,UPDATE,INSERT,EXECUTE TO person;
注意:创建登入名在master数据库下,创建数据库用户和授予数据库权限都是在具体的数据库下操作。
总结
所以如果你想对某个用户某个数据库的权限进行细分,你可以通过GRANT来授予具体的对象给用户(当然你也可以revoke回收权限),也可以通过添加某个架构的权限给用户那么用户就拥有该类架构的权限。
用户拥有什么权限取决于角色,而拥有哪些对象取决于拥有包含这些对象的架构,架构的拥有者可以是数据库用户也可以是数据库角色也可以是应用程序角色,明白了这个道理你对权限的管理也就很清晰了。
虽然心有余但是还是无法将整个知识点给讲透,写文章之前虽然把整个框架给整理了,但是在写的过程中发现要写的内容太多了,比如GRANT权限里面就涉及了表、数据库、应用程序角色、函数、证书、角色、架构、存储过程、同义词还有很多;同时表有可以精确到给具体的某个字段的权限,所以太多了,接下来的REVOKE也同样是这么多。本文可以起到一个引领的作用,让你了解有这些功能,了解权限的功能细分;如果有兴趣的朋友可以更深入的去钻研,这篇文章写下来还是挺累的,写完这篇文章看一下时间已经是凌晨二点钟,主要是思维不想被中断所以一口气给写完了,希望能给大家有所帮助。
备注: 作者:pursuer.chen 博客:http://www.cnblogs.com/chenmh 本站点所有随笔都是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接,否则保留追究责任的权利。 《欢迎交流讨论》 |
SqlServer的权限是相当良好的。但在应用系统进程也要有自己的的权限管理,数据库的是数据库的用户,应用系统是应用系统的用户。
有9种AC元素:Account、Organization、Role、Group、Function、Menu、AppSystem、ResourceType、Privilege。
Privilege的定义是这9种AC元素的任意两两组合,两元中的一元是“主体”,一元是“客体”,主体负责感知客体。区分主客体就是为这两两组合定义了方向。一共是(9 * 8)/(2*1) = 36 + 9 = 45种结果。
在功能级权限的这45种组合中只有一种组合最关键:(Account,Function),主体是Account,客体是Function。其余44种组合的目的最终都是为了得出这个主体为Account客体为Function的组合。
每一个组合实例称作一个Privilege,Privilege也是9种AC元素的一员,有一种组合比较特殊,它是(Privilege,Privilege),这种组合目的是组成Privilege的继承链条,类似面向对象中的继承。另外上面的36+9中的9种是(Account,Account)、(Organization,Organization)、(Role,Role)、(Group,Group)、(Function,Function)、(Menu,Menu)、(AppSystem,AppSystem)、(ResourceType,ResourceType)、(Privilege,Privilege)。
功能级的权限是常驻内存的。
进入数据权限的时候又多了一个元素,第10种元素是Entity或者叫资源记录,数据级权限是10种AC元素的组合。数据级权限和资源记录存储在相同的物理位置,随同对资源记录的访问一起加载进内存,用完后随时丢弃不会常驻内存。
按照rbac标准上的说法是能够完成任何功能级的权限控制的,那么多ac元素最终都是为了得到(account,function)组合,系统运行到一个受控的区域时什么都不管只认(account,function)组合,只问当前用户是否可以执行当前function。
要鉴权只需要知道当前的account和当前正在试图访问的function分别是什么,其中account可以从UserSession中直接读取,而如何识别function相对曲折,对于asp.net mvc来说可以基于这样的约定:ControllerName=ResourceTypeCode,ActionName=FunctionCode,知道了ResourceType.Code和Function.Code就可以直接到FunctionSet中索引到function了。
为了开始构建后100层的数据级权限,anycmd需要尽快为前100层的功能级权限打个好节。
dbo 和Person都是架构名,默认的架构都是以dbo 开头的 一般我们在调用数据库
数据库名.构架名.表名,这种方式在不同的数据库。
当在同一个数据库中时就可以省略数据库名,只需要构架名.表名,这是在表中只有相同的架构的情况下,只需要直接用表名就可以了select * from 表 ,如果存在架构有多种的话就需要在调用中用 构架名.表名 select * from 架构名.表。
他们起到识别功能,比方说表名相同都叫 a,但是一个是dbo 架构的,一个是 Person,在调用过程中是不一样的,select * from dbo.表
select * from person.表 不写架构名则默认为dbo。