1. SQL Server安全体系总览
在SQL Server中谈“数据安全”,不能只盯着某一张表或某一个登录名。SQL Server的安全模型是一个分层、可继承、可覆盖的体系:从最外层的Windows身份验证,到实例级登录名,再到数据库用户、架构、对象权限,每一层都有自己的“主体”和“安全对象”。理解这套体系的关键,是同时回答三个问题:谁在访问(主体)、访问什么(安全对象)、被允许做什么(权限)。这三者组合起来,才构成一条完整的授权链。
本节先建立整体框架,后续章节再逐层展开。我们用一个贯穿全篇的示例来理解:某公司有一台SQL Server实例,域账号 CORP\zhangsan 需要访问数据库 SalesDB 中的 dbo.Orders 表,并只能读取数据。这个看似简单的需求,实际上要穿过四道关卡。
一、主体:安全体系中的“谁”
主体(Principal)是能够请求SQL Server资源的实体。SQL Server的主体分为三个层级,理解层级是理解权限继承的前提。
- Windows级主体:Windows登录名或Windows组,例如
CORP\zhangsan、CORP\DB_Readers。它们由操作系统验证身份。 - 实例级主体:SQL Server登录名(Login),例如
CORP\zhangsan映射的登录名,或SQL登录名app_reader。登录名只负责“能否连上实例”。 - 数据库级主体:数据库用户(User)、数据库角色、应用程序角色。例如
SalesDB中的用户zhangsan。用户负责“在数据库里是谁”。
这里最容易混淆的是登录名与用户:登录名属于实例,用户属于数据库。一个登录名可以在多个数据库中映射为不同名称的用户,也可以在某些数据库中没有用户——没有用户,就连不上该数据库,即使登录名本身有效。
二、安全对象:被保护的“什么”
安全对象(Securable)是权限可以授予的客体。SQL Server的安全对象同样分层:
- 服务器级:服务器本身、端点、可用性组、服务器角色等。
- 数据库级:数据库、架构、数据库角色、证书、非对称密钥等。
- 架构级:架构是对象的容器,也是权限继承的重要节点。
- 对象级:表、视图、存储过程、函数、列等。
权限可以在任意层级授予,并沿层级向下继承。例如在架构 dbo 上授予 SELECT,则该架构下所有表默认都获得查询权限;若只想放开一张表,就应在表级授予,而不是在架构级放开。
三、身份验证与授权:两道不同的门
身份验证(Authentication)解决“你是不是你声称的那个人”,授权(Authorization)解决“你能做什么”。SQL Server支持两种身份验证模式:
- Windows身份验证:由Windows完成身份验证,SQL Server信任其结果。安全性高,支持组管理和密码策略。
- SQL Server身份验证:由SQL Server自己校验登录名和密码。适合跨域、旧系统或应用专用账号。
- 混合模式:同时允许上述两种,是生产环境常见配置。
身份验证通过后,进入授权阶段。授权的基本单位是“权限”,如 SELECT、INSERT、EXECUTE、CONTROL。权限可以授予(GRANT)、拒绝(DENY)、收回(REVOKE)。其中 DENY 优先级最高:即使通过角色继承了允许,只要在更具体层级存在DENY,最终结果就是拒绝。这是排查“为什么明明给了权限还是访问不了”的第一检查点。
四、权限层次与继承关系
把上述内容串起来,就得到一条从实例到对象的授权链。下图展示了示例账号 CORP\zhangsan 访问 SalesDB.dbo.Orders 的完整路径,以及每一层需要满足的条件。
图中可以看到,一次成功的访问需要四层同时成立:Windows身份有效、登录名存在且可连接、数据库用户存在且映射正确、对象权限允许。任何一层缺失或存在DENY,访问都会失败。排查权限问题时,按这个顺序逐层检查,比盲目尝试GRANT要高效得多。
五、角色:权限治理的规模化手段
如果为每个用户单独授予权限,用户一多就会失控。SQL Server提供角色(Role)作为权限的集合容器,分为固定服务器角色、固定数据库角色和用户自定义角色。推荐做法是:权限授予角色,用户加入角色,而不是直接授予用户。例如创建自定义角色 role_order_reader,授予其对 dbo.Orders 的 SELECT,再把 zhangsan 加入该角色。这样新增读者时只需加角色成员,权限模型保持稳定。
db_datareader 可快速赋予整库读取权限,但粒度太粗,生产环境通常只用于只读报表库或临时排查,不建议作为业务权限的长期方案。
六、最小权限与权限审计
安全体系的设计目标不是“能连上就行”,而是最小权限:只给完成工作所必需的权限,且尽量在更细粒度上授予。实现最小权限的常用手段包括:用架构隔离对象、用角色批量管理、用存储过程封装数据访问(只授予 EXECUTE 而不授予表权限)、对敏感列使用列级权限或动态数据掩码。
权限建立后还需要能查。SQL Server提供若干系统视图用于审计:sys.server_principals 查看实例级主体,sys.database_principals 查看数据库级主体,sys.database_permissions 查看数据库内显式权限,sys.fn_my_permissions 查看当前主体在指定对象上的有效权限。例如要确认 zhangsan 对 dbo.Orders 的有效权限,可以执行:
EXECUTE AS USER = 'zhangsan';
SELECT * FROM sys.fn_my_permissions('dbo.Orders', 'OBJECT');
REVERT;
结果中若出现 SELECT,说明读取权限已生效;若为空或只有 CONNECT,则说明授权链在某一层断了。这种“以目标用户身份验证有效权限”的方法,比逐条查看GRANT语句更接近真实访问结果,是权限治理中非常实用的手段。
七、本节要点回顾
- 主体分Windows、实例、数据库三层,登录名与用户不是一回事。
- 安全对象分服务器、数据库、架构、对象四级,权限沿层级继承。
- 身份验证解决“你是谁”,授权解决“你能做什么”,两者不可混为一谈。
- DENY优先于GRANT,是权限排查的首要检查点。
- 用角色管理权限,用系统视图和
EXECUTE AS验证有效权限,是权限治理的基本功。
掌握这套分层模型后,后续无论是配置登录名、设计数据库角色,还是排查“访问被拒绝”,都可以沿着“主体—安全对象—权限—继承与DENY”这条主线定位问题,而不是停留在零散的命令记忆上。