上文我们讲到了最简单的授权——继承固定角色,而没有说明如何为自订角色分配权限,现在我们来说说如何自定义分配权限的问题,包括 权限分类, 安全对象的常用权限, 授予权限, 撤销权限, 否认权限几个方面.
权限分类
大体上而言,权限可以分为两类: 预先定义的权限、预先未定义的权限,它们的区别如下:
- 预先定义的权限: 系统自带的权限,指系统安装之后无需进行授予就有的权限,如固定角色拥有的权限.
- 预先未定义的权限: 需要通过继承/授予才能得到的权限,授权者一般是管理员.
从对象的角度上看,权限还可以分为另外两类:
- 针对特殊对象的权限,如INSERT权限.
- 针对所有对象的权限,如ALTER权限.
下面列出了针对所有对象的一些权限:
权限 | 作用 |
---|---|
CONTROL | 对特定安全对象有控制权,包括对其所有子对象的控制权(一切权限) |
ALTER | 更改特定安全对象的权限 |
ALTER ANY | 更改任意安全对象的权限 |
TAKE OWNERSHIP | 所有权转移,获得对特定安全对象的所有权 |
INPERSONATE | 模拟指定登录名/用户进行对应操作,授权是临时的 |
CREATE | 创建服务器安全对象、数据库安全对象、架构内安全对象的权限 |
VIEW DEFINITION |
下面列出了针对指定安全对象的一些权限:
权限 | 作用对象 | 作用 |
---|---|---|
SELECT | 同义词、表和列、表值函数、视图和列等 | 检索数据权限 |
UPDATE | 同义词、表和列、视图和列等 | 更新数据权限 |
REFERENCES | 标量函数、聚合函数、队列、表和列、表值函数、视图和列等 | 引用对象权限 |
INSERT | 同义词、表和列、视图和列等 | 插入数据权限 |
DELETE | 同义词、表和列、视图和列等 | 删除数据权限 |
EXECUTE | 同义词、标量函数、聚合函数、过程等 | 执行操作权限 |
具体操作不再举例说明,会在后面逐渐接触相应操作.
对象的常用权限
从对象的角度看待权限,往往不同的安全对象对应不同的权限,在授权/撤销操作时,应注意不要搞混对象和权限的对应关系,下表列出了安全对象的常用权限:
安全对象 | 常用权限 |
---|---|
数据库 | BACKUP DATABASE、BACKUP LOG、CREATE DATABASE、CREATE DEFAULT、CREATE FUNCTION、CREATE PROCEDURE、CREATE RULE、CREATE TABLE、CREATE VIEW |
表 | SELECT、DELETE、INSERT、REFERENCES |
表值函数 | SELECT、DELETE、INSERT、REFERENCES |
视图 | SELECT、DELETE、INSERT、REFERENCES |
存储过程 | EXECUTE、SYNONYM |
标量函数 | EXECUTE、REFERENCES |
授予权限
使用GRANT关键字可授予安全对象权限,授权时经常使用ALL表示授予安全对象所能拥有的所有权限.
USE Temp
GO
GRANT CONTROL TO Alex; --将数据库所有权授予Alex;
GO
GRANT CONNECT TO guest; --激活guest;
GRANT CREATE TABLE TO guest; --建表权授予guest;
GO
GRANT CREATE TABLE TO Aveline --建表权授予Aveline;
WITH GRANT OPTION; --且允许Aveline授予其它用户建表权;
GO
上面的代码注释很详细,唯一值得一提的就是WITH GRANT OPTION选项,该选项是指定被授权对象拥有将该权限转授的权限.请看以下的例子:
USE AdventureWorks2017;
GO
GRANT SELECT ON Sales.Customer TO Aaron; --将表的SELECT权限授予Aaron;
GO
GRANT SELECT ON OBJECT::Sales.CurrencyRate TO Aaron --将表的SELECT权限授予Aaron;
WITH GRANT OPTION;
GO
GRANT SELECT ON Sales.Store(Name,SalesPersonID) TO Aaron; --将表指定列的SELECT权限授予Aaron;
GO
分析:
- 第一段授权,使用Sales作为架构名,对Sales架构下的Customer表的SELECT权限授予用户,若不指定架构,则默认使用当前用户默认的架构名,并不建议不指定架构.
- 第二段授权,使用了OBJECT::作为表的限定符,OBJECT::表示对象,可以省略.
- 第三段授权,对Sales.Store中的两列(Name,SalesPersonID)的SELECT权限授予用户,这说明,权限管理方面可以不以整个表为单位,而是以列为单位,即权限可以设置的很细,如下图:

从左侧栏可见,Sales.Store表有很多列,这样授权后,Aaron只拥有对Name和SalesPersonID两列的SELECT权限
还可以对其他对象授权,不仅仅针对用户.比如可以对登录名/自定义角色进行授权,就不一一举例了.
关于GRANT授权,需要注意几点:
- 不同的安全对象拥有不同类型的权限,授权时需要对号入座.
- 授予其它对象权限的对象,至少需要有GRANT OPTION权限,或者是隐含的最高权限(如sa).
撤销权限
使用REVOKE关键字可撤销安全对象权限,撤销时经常使用ALL表示撤销安全对象所拥有的所有权限.
注: REVOKE和GRANT是一对相对关键字,REVOKE只能撤销GRANT授予的权限.
针对上面的例子,使用REVOKE撤销权限:
USE AdventureWorks2017;
GO
REVOKE SELECT ON Sales.Customer FROM Aaron; --撤销Aaron对表的SELECT权限;
GO
REVOKE SELECT ON OBJECT::Sales.CurrencyRate FROM Aaron --撤销Aaron对表的SELECT权限;
GO
REVOKE SELECT ON Sales.Store(Name,SalesPersonID) FROM Aaron; --撤销Aaron对表指定列的SELECT权限;
GO
得到错误提示如下:

第7行,也就是对Sales.CurrencyRate的SELECT权限撤销失败,原因是在授权时使用了GRANT OPTION选项:
按照语法REVOKE只能撤销SELECT权限,而GRANT OPTION权限没有撤销,这就导致对象可以通过GRANT OPTION授予其他对象GRANT OPTION权限,再通过该对象反授权于自身,从而再次获得SELECT权限.
为了避免上面的情况发生,SQL提供了一种可将GRANT OPTION撤销的方法–通过关键字CASCADE(级联)撤销:
USE AdventureWorks2017;
GO
REVOKE SELECT ON OBJECT::Sales.CurrencyRate --撤销Aaron对表的SELECT权限;
FROM Aaron CASCADE;
GO
使用REVOKE的注意点:
- REVOKE只能撤销GRANT授予的权限.
- CASCADE用于撤销GRANT OPTION.
- REVOKE和GRANT作用的安全主体范围一致.
否认权限
由于REVOKE只能撤销GRANT授予的权限,当对象的权限不是用GRANT授予的,而是从角色继承过来时.就不可以用REVOKE撤销了,此时我们使用DENY来否认这些特定权限.
DENY和GRANT用法大致相同,使用时需要注意几点:
- DENY某项权限,则对象无法通过继承某个角色再次被授予该权限,对象进入了否认状态.
- REVOKE可以撤销DENY的权限,使对象退出否认状态,恢复到自然状态.
下面是一个例子:
USE Temp;
GO
EXEC sp_addrolemember 'db_owner','Alex';
GO
DENY SELECT ON dbo.PriceTable TO Alex; --否认Alex对表的SELECT权限;
GO
可以看到,即使是作为db_owner的成员,Alex也无法对表dbo.PriceTable进行SELECT操作:

可以使用REVOKE撤销某个被DENY的权限,使对象回归自然状态:
USE Temp;
GO
REVOKE SELECT ON dbo.PriceTable FROM Alex; --撤销Alex对表的SELECT权限,使其回到自然状态;
GO
自然状态用户Alex继承了db_owner角色,因此可以使用SELECT(虽然dbo.PriceTable然是一张空表):

最后再说一点数据库的安全性设计思路:
- 角色是权限的集合,权限应该先集中在角色中,再用相应对象继承.
- 新建/使用模板定义数据库角色后,使用GRANT语句为角色赋予新权限,再用用户去继承权限.
- REVOKE对于GRANT是撤销权限,对于DENY是撤销状态.
- 特殊情况下可以绕过角色,直接对对象授予某种特权,但应该考虑安全性问题.
以上就是权限管理的全部内容,关于数据库管理的操作,请关注下文.