数据库安全性和完整性

🗨️字数统计=3.4k字 ⏳阅读时长≈13分钟

一、数据库安全性

1. 什么是数据库的安全性

数据库的安全性是指保护数据库以防止不合法使用所造成的数据泄露、更改或破坏

对数据安全性产生威胁的因素主要有以下几个方面

  • 非授权用户对数据库的恶意存取和破坏
  • 数据库中重要或敏感的数据被泄露
  • 安全环境的脆弱性

2. 数据库安全性控制

数据库有关的安全性控制主要包括用户身份鉴别、多层存取控制、审计、视图和数据加密等技术

① 用户身份鉴别

用户身份鉴别是数据库管理系统提供的最外层安全保护措施,每个用户在系统中都有一个用户标识,每个用户标识由用户名和用户标识号UID两部分组成。UID在系统的整个生命周期中是唯一的。系统内部记录着所有合法用户的标识。

每个用户要求进入系统时,由系统进行核对,通过鉴定后才提供使用数据库管理系统的权限。

用户身份鉴别的方法主要有以下几种:

  • 静态口令鉴别

    静态口令一般由用户自己设定,鉴别使输入正确口令即可获得权限

  • 动态口令鉴别

    每次鉴别时均需使用动态产生的新口令登录数据库管理系统。比如短信验证码登录

  • 生物特征鉴别

    比如指纹、虹膜鉴别

  • 智能卡鉴别

    智能卡由用户随身携带,插入专用的读卡器进行身份验证

② 存取控制

数据库安全最重要的一点就是确保只能有资格的用户授予访问权限,这主要通过存取控制机制实现。存取控制机制主要包括定义用户权限和合法权限检查两部分

权限授予和收回

  • GRANT 授予权限

    不允许循环授权,即被授权者不能把权限再授回授权者或者其祖先

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 把查询Student表的权限授给用户User1,并允许他将此权限授予其他用户
    grant select
    on table Student
    to User1
    with grant option;

    # 把对Student表和Cource表的全部操作权限授予用户User2和User3
    grant all privileges
    on table Student,Cource
    to User2,User3;

    # 把对表SC的查询权限授予所有用户
    grant select
    on table SC
    to public;

    # 把查询Student表和修改学生学号的权限授予用户User4
    grant update(Sno),select
    on table Student
    to User4;
  • REVOKE 收回权限

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 收回Uer4修改学生学号的权限
    revoke update(Sno)
    on table Student
    from Uer4;

    # 收回用户User1对Student表的查询权限,并级联收回User1授予的其他用户的该权限
    revoke select
    on table Student
    from User1 CASCADE;

③ 视图机制

还可以为不同的用户定义不同的视图,把要保密的数据对无权存取的用户隐藏起来,从而自动对数据提供一定程度的安全保护。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 建立计算机学生的视图,并把对该视图的select权限授予User1,对该视图的所有操作权限授予User2
create view CS_Student
as
select *
from Student
where Sdept = 'CS';

grant select
on CS_Student
to User1;

grant all privileges
on CS_Student
to User2;

###④ 审计 / 跟踪审查

审计功能把用户对数据库的所有操作自动记录下来放入审计日志(audit log)中。审计员可以利用审计日志监控数据库中的各种行为,重现导致数据库现有状况的一系列事件,找出非法存取数据的人、时间和内容等

  • AUDIT 设置审计功能

    1
    2
    3
    # 对修改Student表结构和修改Student表数据的操作进行审计
    AUDIT alter,update
    on Student;
  • NOAUDIT 取消审计功能

    1
    2
    3
    # 取消取Student 表的一切审计
    noaudit alter,update
    on Student;

⑤ 数据加密

加密的基本思想是根据一定的算法原始数据——明文(plain text) 变换为不可直接识别的格式——密文(cipher text),从而使得不知道解密算法的人无法获知数据的内容。


二、数据库完整性

1. 什么是数据库的完整性

数据的完整性是指数据的正确性和相容性。

  • 数据的正确性:数据是符合现实世界语义,反映当前实际状况的
  • 数据的相容性:数据库同一对象在不同关系表中的数据是符合逻辑的

例如:学生的学号必须唯一,性别只能是男或女等等


为了维护数据库的完整性,DBMS必须提供如下功能

  • 提供定义完整性约束条件的机制
  • 提供完整性检查的方法
  • 进行违约处理

2. 数据库完整性和安全性的区别

  • 数据的完整性是为了防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据。

    因此完整性检查和控制的防范对象是不合语义的、不正确的数据,防止它们进入数据库;

  • 数据的安全性是保护数据库防止恶意破坏和非法存取。

    因此安全性控制的防范对象是非法用户和非法操作,防止他们对数据库数据的非法存取

3. 实体完整性

主键必须存在且不为空

① 定义实体完整性

1
2
3
4
5
create table Student(
Sno char(9) primary key,
Sname char(20) not null,
Ssex char(2)
);
1
2
3
4
5
6
7
# 将SC表中的Sno,Cno属性组定义为主键
create table SC(
Sno char(9) not null,
Cno char(9) not null,
Grade smallint,
primary key(Sno,Cno)
);

② 实体完整性检查和违约处理

  • 检查主键是否唯一,如果不唯一则拒绝插入或修改
  • 检查主键的各个属性是否为空,只要有一个为空则拒绝插入或修改

4. 参照完整性

外键要么不存在,要么存在就不为空

① 定义参照完整性

1
2
3
4
5
6
7
8
create table SC(
Sno char(9) not null,
Cno char(9) not null,
Grade smallint,
primary key (Sno,Cno),
foreign key(Sno) references Student(Sno),
foreign key(Cno) references Cource(Cno)
);

②参照完整性检查和违约处理

当上述的不一致发生时,系统可以采用以下策略

  • 拒绝执行 NO ATION:默认策略

  • 级联操作 CASCADE

    当删除或修改被参照表的一个元组导致与参照表的不一致时,删除或修改参照表中的所有导致不一致的元组。

    例如:删除Student表中001学生,则SC表中关于001的记录也全部删除

  • 设置为空值

    当删除或修改被参照表的一个元组导致与参照表的不一致时,将不一致的属性设置为空值

5. 用户自定义完整性

① 属性上的约束条件

当不满足属性约束条件的时候,操作将被拒绝执行

  • 不允许空值

    1
    2
    3
    4
    create table SC(
    Sno char(9) not null,
    ...
    );
  • 列值唯一

    1
    2
    3
    4
    5
    create table Dept(
    Deptno numeric(2),
    Dname char(9) unique not null, //列值唯一且不能为空
    ...
    );
  • 用check 短语指定列值应该满足的条件

    1
    2
    3
    4
    5
    6
    create table Student(
    Sno char(9) primary key,
    Ssex char(2) check(Ssex in('男','女')), //性别属性只能取男或女
    Grade smallint check(Grade >= 0 and Grade <= 100), //分数属性只能取值0-100
    ...
    );

② 元组上的约束条件

元组级的约束可以设置不同属性之间的相互约束条件。

当不满足这些约束条件的时候,操作将被拒绝执行

1
2
3
4
5
6
create table Student(
Sno char(9),
Sname char(9) not null,
primary key(Sno),
check(Ssex = '女' or Sname not like 'Ms.%') //性别是女或者名字不以MS.%开头则可以通过check检查
);

6. 命名完整性约束 Constraint

① 完整性约束命名

constraint 命名完整性约束,方便增加和删除一个完整性约束条件

格式:constrain 完整性约束条件名 完整性约束条件

完整性约束条件包括

  • not null

  • unique

  • primary key

  • foreign key

  • check

示例

1
2
3
4
5
6
7
8
9
create table Student(
Sno numberic(9)
constraint c1 check (Sno between 100-1000),
Sname char(9)
constraint c2 not null,
Sage numeric(3)
constraint c3 check(Sage < 30),
constrain StudentKey primary key(Sno)
);

② 修改表中的完整性约束

1
2
3
4
5
6
7
# 去除对年龄小于30的约束
alter table Student
drop constraint c3;

# 添加年龄小于40的约束
alter table Student
add constraint c4 check(Sage < 40);

7. 断言 ASSERTION

关键词:ASSERTION

任何对断言中所涉及关系的操作都会触发关系数据库管理系统对断言的检查,任何使断言不为真值的操作都会被拒绝执行

示例:

1
2
3
4
5
6
7
# 限制数据库课程最多60名学生选修
create assertion asse_sc_db_num
check (60 >= (select count(*)
from Cource,SC
where SC.Cno = Cource.Cno and
Couce.Cname = '数据库')
);

8. 触发器 Trigger

触发器是用户定义在关系表上的一类由事件驱动的特殊过程

① 创建触发器

触发器仅限于数据库中增 删 改三种操作

触发器定义如下:

1
2
3
4
5
6
7
create trigger 触发器名 
before/after 触发事件 /*指明触发器的激活时间*/
on 表名 /*触发器只能定义在基本表上,不能定义在视图上*/
[referencing 引用名] 可选的
for each row/statement /*定义触发器的类型,指明动作体执行的频率*/
when SQL语句
动作

before/after:触发器必须指定在语句执行之前还是之后自动执行,之前执行使用 BEFORE 关键字,之后执行使用 AFTER 关键字。BEFORE 用于数据验证和净化,AFTER 用于审计跟踪,将修改记录到另外一张表中。

触发事件

  • insert:触发器包含一个名为 NEW 的虚拟表。

  • delete :触发器包含一个名为 OLD 的虚拟表,并且是只读的。

  • update:触发器包含一个名为 NEW 和一个名为 OLD 的虚拟表,其中 NEW 是可以被修改的,而 OLD 是只读的。

    也可以是 update of < 触发列名1,触发列名2 ... >

引用名:

触发器事件既然是数据库更新操作,这些操作的执行势必会引起数据库中某些值的改变,即由旧值变成新值,这些新旧值称为过渡值。在触发器的条件和动作中可以引用这些过渡值

  • OLD【ROW】AS 旧元组别名 (row旧元组名是可选的)
  • NEW【ROW】AS 新元组别名
  • OLD TABLE AS 旧表别名
  • NEW TABLE AS 旧表别名

触发器类型:

  • for each row:行级触发器

  • for each statement : 语句级触发器

    比如修改一个Teacher表中的deptno字段(一共1000条记录)

    update teacher set deptno = 5;

    若是行级触发器,update后触发动作执行一次

    若是语句级触发器,触发动作将执行1000次

示例:

cource表中删除一个元组,若该元组的主键是sc表中的外键,则卷回删除该元组的操作。

1
2
3
4
5
6
7
CREATE TRIGGER mytrigger 
BEFORE DELETE ON cource
referencing old as o
for each row
when (exists (select * from sc
where cno = o.cno))
ROLLBACK;

② 删除触发器

1
DROP TRIGGER 触发器名

③ 触发器实现参照完整性

比如有三个表:student(学生表),cource(课程表),sc(选修表),其中sc定义了两个外键sno和cno以及其完整性约束,试写出触发器实现该参照完整性约束的规则

首先分析:有哪些操作会影响到本例的完整性约束

  • sc 表的 insert 操作
  • cource 表的 delete 操作
  • student 表的 delete 操作
  • sc 表的 update(sno, cno) 操作
  • cource 表的 update(cno) 操作
  • student 表的 update(sno) 操作

对上述6中操作分别定义6条规则,实现参照完整性约束

规则1:

1
2
3
4
5
6
7
8
9
10
11
create trigger referential_integrity_check
before insert on sc
referencing new as n
when (not(exists(select * from student
where sno = n.sno)
and
exists(select * from cource
where cno = n.cno)
)
)
rollback;

如果 sc 表中插入元组,其外键在 student 和 cource 表中均不存在,则卷回插入该元组操作

规则2:

1
2
3
4
5
6
7
8
create trigger cource_delete
before delete on cource
referencing old as o
for each row
when (exists(select * from sc
where o.cno = sc.cno)
)
rollback;

如果 cource 表中删除一个元组,若该元组是 sc 表中的外键,则卷回删除该元组的操作(此处我们假定在sc表的定义中,外键 cno 使用了 restrict 选项)

规则3:

1
2
3
4
5
6
7
8
9
create trigger student_delete
before delete on student
referencing old as o
for each row
when(exists(select * from sc
where sc.sno = o.sno)
)
delete from sc
where sc.sno = o.sno;

假设在 sc 表的定义中,外键 sno 的定义中采用了 cascade 选项,即当在 student 表中删除一个元组的时候,则在 sc 表中删除引用该元组主键作为外键的所有元组

规则4:

1
2
3
4
5
6
7
8
9
10
11
12
create trigger sc_fk_update
before update of sno,cno on sc
referencing new as n
for each row
when(not(exists(select * from student
where sno = n.sno)
and
exists(select * from cource
where cno = n.cno)
)
)
rollback;

对于 sc 表的更新操作,若更新的外键 sno 或者 cno 在 student 和 cource 表中无相应的主键供其引用,则卷回更新该元组的操作

规则5:

1
2
3
4
5
6
7
8
9
create trigger cource_cno_update
before update of cno on cource
referencing old as o
for each row
when(exists(select * from sc
where sc.cno = o.cno)
)

rollback;

对于 cource 表的 更新操作,在修改主键cno的同时,如果sc表中有元组正引用修改前的cno值作为外键,则卷回该操作

规则6:

1
2
3
4
5
6
7
8
create trigger student_sno_update
before update of sno of student
referencing old as o
for each row
when (exists(select * from sc
where sc.sno = o.sno)
)
rollback;

对于 student 表的更新操作,在修改主键sno的同时,如果sc表中有元组正引用修改前的sno值作为外键,则卷回该操作

分享到