本节摘要:身份验证决定"你是谁",授权决定"你能做什么"——两者合起来是数据库的门禁系统。本节讲清双轨验证的取舍、登录名与用户的两级身份映射、角色与架构的权限落地,以及行级安全这类精细控制。核心论点只有一个:最小权限不是口号,是一张可以画出来的角色矩阵。
内审发现:报表系统的运维账号能直接改客户表数据——追查发现,两年前某次紧急修复时有人图省事把账号加进了 db_owner 固定角色,事后没人记得回收。这不是个案,而是"权限一把抓"模式的必然结局:临时授权没有生命周期,就会永久化。治理这一案的方案就是本节的骨架:先用角色矩阵把"谁需要什么"显式化,再把临时授权纳入变更管理并设回收日期。权限设计的第一步不是给权限,而是先回答"这个账号到底要干哪几件事"。
Windows 身份验证用域凭据登录,密码不经过数据库,策略(复杂度、锁定、过期)由域统一管——内网域环境的首选。SQL 身份验证由实例自管账号密码,适合跨域、非 Windows 客户端与部分老应用;代价是密码策略要自己管,且密码会出现在连接串里的风险需要靠加密连接与密钥管理对冲。实践中多数企业用混合模式:人与内网服务走域账号,少量外部集成走 SQL 账号并纳入密钥轮换。
验证之后是授权,而授权的第一道坎是两级身份模型:登录名(login)是实例级的门卡,数据库用户(user)是库内的工牌,门卡要映射成工牌才有库内身份。新人常犯的错是只建了登录名没建用户(或者反过来),表现为"能连上却看不到库"。映射有两种写法:常规映射按登录名,包含可用性组环境(Always On)则推荐包含用户(contained user,密码或 Windows 凭据直接建在库内)——它随库走,切换副本不丢身份,避免"切换成功、登录失败"的经典事故(第 6 章演练清单里的"登录同步"问题的根治法)。
-- 标准授权流水线:登录名 → 用户 → 角色 → 授权 CREATE LOGIN [CORP\report_svc] FROM WINDOWS; -- 实例门卡(域账号) GO USE 订单库; CREATE USER [CORP\report_svc] FOR LOGIN [CORP\report_svc]; -- 库内工牌 CREATE ROLE r_reader; CREATE ROLE r_report; ALTER ROLE r_report ADD MEMBER [CORP\report_svc]; -- 只进业务角色,不进固定角色 GRANT SELECT ON SCHEMA::dbo TO r_reader; -- 角色拿权限,人不直接拿 DENY UPDATE ON SCHEMA::dbo TO r_report; -- 显式拒绝优先于授予
权限沿"服务器级 → 数据库级 → 架构级 → 对象级"四层传导,上层授予向下继承。设计纪律按四条走。第一,人进角色、角色拿权限:账号永远不直接 GRANT,权限矩阵变更只改角色定义,审计时 rolespeak 比散落的账号清晰一个量级。第二,固定服务器角色当雷区看:sysadmin 一票通行全实例,成员数用告警盯着(超过个位数就要解释);bulkadmin、diskadmin 这类高危角色默认清空。第三,架构当权限的打包单位:把表按业务域放进架构(sales、hr、fin),授权对架构一把给,新人建表放错架构比放错权限好纠正。第四,拒绝优先:DENY 覆盖 GRANT,用于在宽授权上挖例外(比如给财务角色全读权限但拒绝读薪酬表)。
精细场景还有两件武器。行级安全(Row-Level Security)用安全谓词函数按会话上下文过滤行:租户 SaaS 里每个租户账号自动只见自己的行,应用代码一行不改;动态脱敏在 7.2 细讲,但它本质也是授权的延伸——"看得见格式看不见内容"。两者共同的特点是策略集中在库内,而不是散落在几百个查询里——安全策略离数据越近,越不容易被绕过。
⚠️ 权限链有个隐蔽环节:跨库与跨所有者的访问会走所有权链,链通则中间检查被跳过。用 EXECUTE AS 切换执行上下文的模块要显式核对链路,否则"表级 REVOKE 了却照样能查"的灵异事件就是它。
把最小权限落成配置,多数库只需要五个角色。应用读写角色:对业务架构授增删改查,拒绝结构变更;只读报表角色:全架构查询权,拒绝一切写入与临时表写入(防报表抢占 tempdb);运维角色:结构变更加作业管理,不含数据读取(运维改结构不必看数据,按需临时授权);审计角色:审计日志与目录视图只读,独立于运维——审计者不归被审计者管;紧急通道角色:更高的权限,成员加入要工单、按天回收。这张矩阵的价值不在完备而在"每条授权都能回答为什么":内审时五个角色五句话讲清楚,远胜五十个散落授权的解释成本。
配套的年检脚本一行不复杂:列出实例上所有角色的成员与权限授予,与矩阵定义比对,差异进评审。权限治理的成熟度,不取决于用了多细的功能,而取决于偏离定义的授权能在多久内被发现——年检脚本把这个周期从"内审来查"压缩到"每月自动"。
角色矩阵之外,应用账号再加三道箍。连接数上限:给应用账号设会话数上限,连接池失控时保护的是整台实例而不是单个应用。默认架构指定:应用用户的默认架构指向专属架构,防止它把临时对象建进别人地盘。DDL 触发器拦戒:生产库上挂一条库级触发器,拦截应用账号的结构变更尝试并记审计——应用侧的框架迁移脚本误连生产库,是真实世界里最常见的越权事故之一,一道触发器能把事故变成一条告警。三道箍的配置成本不到半小时,换来的是应用与运维的安全边界从"约定"变成"机制"。
门禁设计好了,但拿到工牌的人也可能把数据搬走。下一章换武器:让"看见也看不懂、该露的才露"的加密与脱敏体系。