惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
罗磊的独立博客
腾讯CDC
云风的 BLOG
云风的 BLOG
月光博客
月光博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
U
Unit 42
I
InfoQ
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
美团技术团队
IT之家
IT之家
Stack Overflow Blog
Stack Overflow Blog
F
Fortinet All Blogs
GbyAI
GbyAI
S
SegmentFault 最新的问题

博客园 - Danny Chen

python asyncio 获取协程返回值和使用callback c#等待所有子线程执行完毕方法 Python virtualenv 查看当前正在运行的python进程 Mac 删除/卸载 自己安装的python python读取txt文件最后一行(文件大+文件小) pycharm 注册码/License server 2017年最新 Linux cat命令详解 在Mac平台上安装配置ELK时的一些总结 Mac上搭建ELK C#中用schema验证xml的合法性 C#中XML与对象之间的序列化、反序列化 C#位运算 如何用C#动态编译、执行代码 [C#]手把手教你打造Socket的TCP通讯连接(一) C#动态调用WCF接口,两种方式任你选。 动态调用WCF服务 矩阵的坐标变换(转) 【.NET线程--进阶(一)】--线程方法详解
SQL Server 权限管理
Danny Chen · 2017-06-16 · via 博客园 - Danny Chen

概述

      对数据库系统而言,保证数据的安全性永远都是最重要的问题之一。一个好的数据库环境,必须明确每个用户的职责,并分配其对应的权限。同时出现问题了也可以找到根源。

你是否会有这样的需求:

  1. 给某个用户查询所有数据库的权限
  2. 给某个用户只有备份数据库的权限
  3. 给一个用户只有指定数据库的权限
  4. 给一个用户只有某个表的权限
  5. 给一个用户只有查看某些对象(例如:视图)的权限
  6. 给一个用户只有执行一些存储过程的权限

目录

元素

文章可能会有些枯燥,还望耐心,相信应该有你想要的。

登入名

只有拥有了登入名才能访问实例(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也同样是这么多。本文可以起到一个引领的作用,让你了解有这些功能,了解权限的功能细分;如果有兴趣的朋友可以更深入的去钻研,这篇文章写下来还是挺累的,写完这篇文章看一下时间已经是凌晨二点钟,主要是思维不想被中断所以一口气给写完了,希望能给大家有所帮助。

如果文章对大家有帮助,希望大家能给个赞,谢谢!!!