前言
最近有个做Java开发的网友问我,怎么在Oracle进行数据加密呢?
我给他推荐了Data Redaction。
Oracle Database 12c中加入了Data Redaction这个新的安全特性。当然在11g的Database Advanced Security Administrator's Guide官方文档中就介绍了。如果你想要隐藏一个字段所有值或部分值的话,而且还要为用户提供他们需要的信息的时候,或则换句话说,你想仅某些用户看到的一些数据是隐藏的,但是另一些用户看到的是正常的数据,就可以用Data Redaction~
一、介绍
官方链接:
对于列中的数据有以下几种redaction方式:
1、Full redaction
对列中的数据全部redact,number类型的列将全部返回为0,character类型的列将全部返回为空格,日期类型返回为2001-01-01。
2、Partial redaction
对列中的一部分数据进行redact,比如,可以对社会保险号的前几位设置返回为*,剩下的几位保持不变。只有列中的数据为固定宽度时才能使用这种方式,如果列中存储的是email地址,每个email地址的宽度不尽相同,此时要使用Regular expressions。
3、Regular expressions
可以使用正则表达式查找要编校的数据模式。例如,您可以使用正则表达式编校电子邮件地址,电子邮件地址可以具有不同的字符长度。它仅设计用于字符数据。
4、Random redaction
提供给查询用户的编校数据每次显示时都显示为随机生成的值,这取决于列的数据类型。
5、No redaction
此选项使您能够测试编校策略的内部操作,而不影响对定义了策略的表的查询结果。在将编校策略定义应用到生产环境之前,可以使用此选项测试它们。
`重点关注:
不能对sys和system用户进行数据的redact。因为他们都有EXP_FULL_DATABASE这个角色, 而这个角色又包含了EXEMPT REDACTION POLICY系统权限。同理,也不能直接赋予用户dba权限,dba自动包含EXP_FULL_DATABASE角色。`
二、部分功能测试
创建测试用户
create user zhaoyd identified by zhaoyd;
create user zhaojh identified by zhaojh;
grant connect,resource to zhaoyd;
grant select on sys.redaction_policies to zhaoyd;
grant select on sys.redaction_columns to zhaoyd;
grant execute on dbms_redact to zhaoyd;
给zhaoyd用户建一张表名为emp:
编辑策略:
1、将phone字段中间4位数值用*号替代
begin
dbms_redact.add_policy(object_schema => 'ZHAOYD',
object_name => 'EMP',
policy_name => 'test_zhaoyd_emp',
column_name => 'PHONE',
function_type => Dbms_Redact.PARTIAL,
expression => '1=1',
function_parameters => 'vvvvvvvvvvv,vvvvvvvvvvv,*,4,7');
end;
2、将地址LOC字段给完全隐藏
begin
dbms_redact.alter_policy(object_schema => 'ZHAOYD',
object_name => 'EMP',
policy_name => 'test_zhaoyd_emp',
action => dbms_redact.ADD_COLUMN,
column_name => 'LOC',
function_type => Dbms_Redact.RANDOM);
end;
3、分别查询看效果
zhaoyd,zhaojh,sys用户分别查询这个表:
可以看到sys用户查询是不会受策略限制的。
创建角色,用角色来控制,只让被赋予这个角色的用户看到的数据是加密的:
create role redac_role;
grant redac_role to zhaojh;
接下来修改之前的策略:
begin
dbms_redact.alter_policy(object_schema => 'ZHAOYD',
object_name => 'EMP',
policy_name => 'test_zhaoyd_emp',
action => dbms_redact.MODIFY_EXPRESSION,
column_name => 'LOC',
expression => 'SYS_CONTEXT(''SYS_SESSION_ROLES'',''REDAC_ROLE'') = ''TRUE''');
end;
这时候再分别用zhaoyd,zhaojh,sys用户分别查询zhaoyd.emp:
给zhaoyd用户赋予角色redac_role:
zhaoyd用户看到的也是加密后的了。
总结
经过实际测试的出来的一些结果
- 对加密的列不能同时使用distinct和order by,如果使用,必须加一层select,无论对于使用的用户是否是加密可见;
- 加密的结果优先级高于函数,比如distinct;
- 对于group by不影响结果的准确性,与未加密结果一致;
- 加密后的表无法进行CTAS(create table as select)操作;