数据库系统の安全与完整性:谁来保护你的数据?
你存在银行的钱、你的社交账号密码、你的体检报告——这些数据在数据库里,到底靠什么保证不被偷看、不被乱改?
数据库的"保护伞"有两把:安全性防的是"坏人"(非法用户),完整性防的是"坏数据"(非法操作)。这篇文章把这两把伞从里到外讲透——身份鉴别怎么验明正身、GRANT/REVOKE怎么管权限、三大完整性约束怎么防错数据、触发器怎么自动兜底。期末考试要考安全与完整性的同学,这一篇就够了。
本文目录
安全性概述:数据库面临哪些威胁?
身份鉴别:你是你吗?
存取控制:DAC与MAC
视图、审计与加密
完整性概述:防"坏数据"
三大完整性约束详解
高级完整性机制:触发器与断言
安全性 vs 完整性:一文厘清
一、安全性概述:数据库面临哪些威胁?
1.1 什么是数据库安全性?
数据库安全性,简单说就是:防止非法用户对数据库的非法使用,防止合法用户对数据库的非法操作。
核心目标是防止数据被泄露、篡改或破坏。
数据库安全面临的威胁与防护方法
注意一个常见混淆:安全性 ≠ 完整性。
安全性防的是"谁在操作"(Who)——不让不该碰数据的人碰到数据。
完整性防的是"操作什么"(What)——不让合法用户往数据库里塞错误数据。
打个比方:安全性是"门禁"(只有持卡人能进大楼),完整性是"规章制度"(进了大楼也不能乱扔垃圾)。
1.2 数据库面临的四大威胁
非授权用户存取数据——没有账号的黑客通过SQL注入等手段非法访问数据。
授权用户越权操作——有合法账号但干了不该干的事。比如一个普通员工偷偷查看了全公司的工资表。
数据泄露(推理攻击)——用户虽然不能直接看到敏感数据,但可以通过多次查询的结果"推理"出来。比如查"部门A的平均工资"和"部门A除张三外的平均工资",两个一减就能算出张三的工资。
拒绝服务攻击(DoS)——通过大量无效请求耗尽数据库资源,让正常用户无法使用。
1.3 安全控制的五大方法
面对这些威胁,DBMS提供了五层防护:
身份鉴别(Authentication)——验明正身,确认"你是谁"。
存取控制(Authorization)——权限管理,决定"你能做什么"。
审计(Audit)——操作记录,追踪"你做了什么"。
数据加密(Encryption)——数据保护,即使被偷走也看不懂。
视图机制(View)——数据过滤,只让你看到该看的部分。
二、身份鉴别:你是你吗?
用户要访问数据库,首先得证明"我是我"。身份鉴别是安全控制的第一道关卡。
2.1 静态口令鉴别
最常见的方案:用户名 + 密码。简单、成本低,但安全性也最低——密码可能被猜到、被偷看、被暴力破解。大多数数据库系统(MySQL、Oracle等)都支持这种方式。
2.2 动态口令鉴别
一次性密码(OTP)——每次登录的密码都不同。常见形式:手机短信验证码、动态令牌(银行U盾)。比静态口令安全得多,因为即使本次密码被偷窥,下次也用不了。
2.3 生物特征鉴别
利用指纹、虹膜、面部识别等生物特征来鉴别。安全性高、不可伪造,但成本也高。目前主要用于高安全级别的场景(如银行金库、军事设施)。
2.4 数字证书鉴别
基于PKI(公钥基础设施),用数字证书证明身份。安全性最高,常用于网络传输和重要系统之间的身份认证。
三、存取控制:DAC与MAC
身份鉴别解决了"你是谁"的问题,存取控制解决"你能做什么"。
3.1 自主存取控制(DAC)
DAC与MAC:两种存取控制方式对比
DAC(Discretionary Access Control)——数据的所有者可以自主决定把数据的使用权限授予谁。这是最灵活、最常用的存取控制方式。
GRANT:授权
GRANT SELECT ON TABLE Employee TO Alice; GRANT INSERT, UPDATE ON TABLE Student TO Bob; GRANT ALL PRIVILEGES ON TABLE Course TO Charlie;GRANT语句的格式:GRANT 权限 ON 对象 TO 用户。权限包括SELECT(查询)、INSERT(插入)、UPDATE(修改)、DELETE(删除)、ALL PRIVILEGES(全部权限)。
WITH GRANT OPTION——如果加上这个选项,被授权的用户还可以把权限转授给其他人。这就形成了一个"权限链":
GRANT SELECT ON TABLE Employee TO Alice WITH GRANT OPTION; -- Alice 可以再授权给 Bob GRANT SELECT ON TABLE Employee TO Bob; -- Alice执行REVOKE:回收权限
REVOKE SELECT ON TABLE Employee FROM Alice; REVOKE INSERT ON TABLE Student FROM Bob CASCADE;CASCADE(级联回收)——如果Alice曾经把权限转授给了Bob,那么回收Alice的权限时,Bob的权限也会被一起回收。这是为了防止权限链失控。
3.2 强制存取控制(MAC)
MAC(Mandatory Access Control)——系统强制实施存取规则,用户不能自行控制。主要用于高安全性场景(军事、政府)。
MAC给每个数据对象和每个用户分别标记密级。密级从低到高:公开 < 秘密 < 机密 < 绝密。
MAC的核心规则只有两条:
读向下(Read Down)——用户只能读取密级不高于自己安全级别的数据。绝密级用户可以读所有数据,公开级用户只能读公开数据。
写向上(Write Up)——用户只能写入密级不低于自己安全级别的数据。这是为了防止高密级用户把敏感信息写到低密级的数据对象中(信息泄露)。
DAC与MAC的关系——DAC是基础,MAC更严格。实际系统中,先检查DAC(用户有没有被授权),通过后再检查MAC(用户的密级是否满足要求)。
3.3 角色(Role)
当用户很多时,逐个授权太麻烦。角色(Role)把一组权限打包:
CREATE ROLE manager; GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE Employee TO manager; GRANT manager TO Alice, Bob, Charlie; -- 一次性给三个人授权角色的好处:简化权限管理。员工入职时授予角色,离职时回收角色,权限变更时只需修改角色的权限定义。
GRANT与REVOKE:权限的授予与回收
四、视图、审计与加密
4.1 视图的安全作用
视图(View)是一种虚拟表,它不存储实际数据,而是从基本表中查询数据。视图的安全作用在于:
隐藏敏感列——比如员工表有"工资"列,可以通过视图只暴露姓名、部门,隐藏工资。
限制行级访问——比如普通部门经理只能看到本部门员工的数据。
CREATE VIEW EmpView AS SELECT Ename, Dno, Job FROM Employee; -- 用户查询EmpView时看不到Salary列但视图的安全能力有限——它只是辅助手段,不能替代DAC和MAC。
4.2 审计(Audit)
审计就是"装监控"——记录用户对数据库的所有操作:谁在什么时间对什么数据做了什么。
审计日志用于事后追踪和安全分析。比如发现数据被篡改了,可以查审计日志找到是谁在什么时间做的修改。
审计的代价:每次操作都需要额外写日志,会影响系统性能。因此审计通常只在高安全性要求的环境中开启。
4.3 数据加密
即使攻击者绕过了所有身份鉴别和存取控制,把数据偷走了,加密也能让他们拿到的只是一堆乱码。
透明数据加密(TDE)——对应用层透明,数据库自动加密和解密。应用不需要改代码。
应用级加密——应用层加密后存入数据库,数据库本身存的是密文。安全性更高,但应用需要处理加解密逻辑。
列级加密——只对敏感列(如密码、身份证号)加密,其他列不加密。
加密算法分两类:
对称加密(如AES)——加解密使用同一个密钥,速度快,适合大量数据。
非对称加密(如RSA)——公钥加密、私钥解密,安全性更高,常用于密钥交换和数字签名。
五、完整性概述:防"坏数据"
从这一节开始,话题从"防坏人"转向"防坏数据"。
5.1 什么是完整性?
完整性(Integrity)是指数据的正确性(Correctness)和相容性(Compatibility)。
正确性:数据是否符合现实世界的事实。比如年龄不能是负数,性别只能是"男"或"女"。
相容性:同一事物在不同地方的描述是否一致。比如学生表里张三的学号和选课表里张三的学号必须一致。
5.2 完整性控制的三个环节
定义完整性约束——声明数据必须满足什么条件。比如"主码不能为空"、"年龄必须在0到150之间"。
检查完整性约束——每当用户执行插入、修改、删除操作时,DBMS自动检查操作是否违反了已定义的约束。
处理违约操作——如果违反了约束怎么办?拒绝操作?级联修改?还是置为空值?
六、三大完整性约束详解
6.1 实体完整性
三大完整性约束:实体完整性、参照完整性、用户定义完整性
规则:主码不能为空(NOT NULL),且主码值必须唯一。
为什么?因为主码的作用是唯一标识一个元组(一行记录)。如果主码为空,就无法区分不同的元组;如果主码重复,就无法唯一确定某个元组。
定义方式:
-- 列级约束 CREATE TABLE Student ( Sno CHAR(9) PRIMARY KEY, Sname VARCHAR(20) NOT NULL ); -- 表级约束 CREATE TABLE SC ( Sno CHAR(9), Cno CHAR(4), Grade INT, PRIMARY KEY (Sno, Cno) -- 复合主码 );违反处理:直接拒绝插入或更新操作。比如试图插入一条Sno为空的记录,DBMS会报错并拒绝。
6.2 参照完整性
规则:外码的值必须是被引用关系主码的有效值,或者为空值(NULL)。
为什么?因为外码表示的是"引用关系"——比如学生表里的"院系编号"引用了院系表的主码。如果学生的院系编号在院系表中不存在,就意味着这个学生属于一个"不存在的院系"——这显然是不合理的。
定义方式:
CREATE TABLE Student ( Sno CHAR(9) PRIMARY KEY, Sname VARCHAR(20), Dno CHAR(3), FOREIGN KEY (Dno) REFERENCES Department(Dno) );参照完整性的四种违约处理策略
违约处理策略——当操作导致参照完整性被违反时,有四种处理方式:
NO ACTION(拒绝)——直接拒绝导致违约的操作。这是默认策略,也是最安全的。
CASCADE(级联)——连带执行相关操作。比如删除一个院系时,自动删除该院系下所有学生。
SET NULL(置空)——将外码值设为NULL。比如删除一个院系时,该院系学生的院系编号设为空。
SET DEFAULT(置默认值)——将外码值设为预定义的默认值。
CREATE TABLE Student ( Sno CHAR(9) PRIMARY KEY, Dno CHAR(3), FOREIGN KEY (Dno) REFERENCES Department(Dno) ON DELETE CASCADE -- 删除院系时级联删除学生 ON UPDATE SET NULL -- 修改院系编号时将学生院系置空 );选择哪种策略取决于具体业务需求。一般情况下NO ACTION最安全,CASCADE适合"父子关系"(订单和订单明细)。
6.3 用户定义完整性
除了实体完整性和参照完整性这两种"通用"约束,每个应用还有自己特定的数据约束——这就是用户定义完整性。
NOT NULL——非空约束。某些属性不能为空(如姓名)。
UNIQUE——唯一约束。某些属性的值不能重复(如身份证号)。
CHECK——检查约束。属性值必须满足指定条件:
CREATE TABLE Student ( Sno CHAR(9) PRIMARY KEY, Sname VARCHAR(20) NOT NULL, Sage INT CHECK (Sage >= 15 AND Sage <= 45), Ssex CHAR(2) CHECK (Ssex IN ('男', '女')), Dno CHAR(3) UNIQUE );DEFAULT——默认值。如果插入时没有指定该列的值,自动使用默认值。
七、高级完整性机制:触发器与断言
7.1 触发器(Trigger)
触发器是一种特殊的存储过程——在特定事件发生时自动执行。
CREATE TRIGGER delete_student_courses AFTER DELETE ON Student FOR EACH ROW BEGIN DELETE FROM SC WHERE Sno = OLD.Sno; END;这个触发器的含义:当从Student表中删除一条记录时,自动从SC(选课)表中删除该学生的所有选课记录。
触发器三要素:触发事件(INSERT/UPDATE/DELETE)、触发时机(BEFORE/AFTER)、触发器体(要执行的SQL语句)。
触发器的用途很广:实现复杂的完整性约束(跨表约束)、自动审计(记录谁在什么时间修改了什么数据)、自动维护派生数据(如自动更新统计表)。
7.2 存储过程(Stored Procedure)
存储过程是预编译的SQL语句集合,可以包含业务逻辑和完整性检查。
CREATE PROCEDURE enroll_student(IN sno CHAR(9), IN cno CHAR(4)) BEGIN DECLARE max_cap INT; SELECT capacity INTO max_cap FROM Course WHERE Cno = cno; IF (SELECT COUNT(*) FROM SC WHERE Cno = cno) < max_cap THEN INSERT INTO SC VALUES (sno, cno, NULL); ELSE SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '课程已满'; END IF; END;存储过程的好处:封装业务逻辑(选课人数限制在过程里检查,不用每个应用都写一遍)、减少网络传输(一次调用完成多个操作)、提高性能(预编译,不用每次解析SQL)。
7.3 断言(Assertion)
断言是一种更一般化的完整性约束,可以涉及多个表的全局约束:
CREATE ASSERTION student_course_limit CHECK (NOT EXISTS ( SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*) > 10 ));这个断言的含义:每个学生最多选10门课。
断言功能强大,但目前大多数主流DBMS(MySQL、PostgreSQL等)并不完全支持断言。实际开发中,通常用触发器或存储过程来替代断言实现类似的全局约束。
八、安全性 vs 完整性:一文厘清
安全性与完整性:两种不同的数据保护机制
这两个概念容易混淆,这里做一个清晰的对比:
对比维度 | 安全性(Security) | 完整性(Integrity) |
|---|---|---|
保护对象 | 防止非法用户/非法操作 | 防止错误数据/不一致数据 |
核心问题 | Who——谁能访问数据? | What——什么数据是合法的? |
比喻 | 门禁系统 | 规章制度 |
主要手段 | 身份鉴别、授权、加密、审计 | 约束、触发器、存储过程 |
SQL实现 | GRANT/REVOKE | PRIMARY KEY/FOREIGN KEY/CHECK/触发器 |
违反后果 | 数据泄露、被篡改、被破坏 | 数据错误、不一致、失去意义 |
两者的联系:它们相辅相成,共同保护数据库。视图既是安全机制(限制用户只能看到部分数据),也是完整性的辅助手段。触发器可以同时服务于安全(审计触发器记录操作)和完整性(约束触发器检查数据)。
总结
数据库的"保护伞"有两把,缺一不可:
安全性——五层防护层层把关:身份鉴别(你是谁)→ 存取控制(你能做什么,DAC用GRANT/REVOKE管理权限,MAC用密级控制读写)→ 视图(只让你看该看的)→ 审计(记录你做了什么)→ 加密(即使偷走也看不懂)。
完整性——三个环节环环相扣:定义约束(声明规则)→ 检查约束(操作时自动验证)→ 处理违约(拒绝/级联/置空/默认值)。三大完整性约束各司其职:实体完整性保主码、参照完整性保引用、用户定义完整性保业务规则。高级机制(触发器、存储过程、断言)处理更复杂的场景。
一句话总结:安全性是"不让不该碰数据的人碰到数据",完整性是"不让合法的人往数据库里塞垃圾数据"——一个防外贼,一个防内鬼(的失误)。