ALTER TABLE table_name
CHANGE COLUMN column_name
SET MASK schema_name.masking_function;
添加列时指定脱敏:
ALTER TABLE table_name ADD COLUMN (column_name column_type MASK schema_name.masking_function);
3 解除策略绑定
ALTER TABLE table_name
CHANGE COLUMN column_name
UNSET MASK;
查询者所需权限
脱敏函数在读取数据时执行。查询者除了需要表的
SELECT
SELECT
权限,还必须拥有查询过程中执行的每个脱敏函数的
USE FUNCTION
USE FUNCTION
权限:
GRANT SELECT ON TABLE schema_name.table_name TO USER user_name;
GRANT USE FUNCTION ON FUNCTION schema_name.masking_function TO USER user_name;
如果一条查询会执行多个脱敏函数,需要逐个授予
USE FUNCTION
USE FUNCTION
权限。
⚠️ 注意:
USE FUNCTION
USE FUNCTION
只允许执行脱敏函数,不会授予查看原始值的权限。函数仍根据查询者的
current_user()
current_user()
和
current_roles()
current_roles()
选择返回原始值还是脱敏值。缺少任一所需函数的
USE FUNCTION
USE FUNCTION
权限时,查询会以
NoPermission
NoPermission
错误整体失败,不会将对应列返回为
NULL
NULL
或脱敏值。
使用场景示例
1 基础脱敏
需求:身份证号前6位+4星号+后4位
CREATE FUNCTION public.idcard_masking(idcard STRING)
RETURNS STRING
AS concat(substr(idcard, 1, 6), repeat('*', 4), substr(idcard, 10, 4));
ALTER TABLE data CHANGE COLUMN idcard SET MASK public.idcard_masking;
查询效果:
原始值:130183199901011234 → 脱敏后:130183****9010
2 基于用户的动态脱敏
需求: 仅UAT_TEST用户看到脱敏数据
CREATE FUNCTION public.idcard_masking(idcard STRING)
RETURNS STRING
AS
CASE
WHEN current_user() = "UAT_TEST"
THEN concat(substr(idcard, 1, 6), repeat('*', 4), substr(idcard, 10, 4))
ELSE idcard
END;
--忽略用户名大小写
CREATE FUNCTION public.idcard_masking(idcard STRING)
RETURNS STRING
AS
CASE
WHEN lower(current_user()) = "uat_test"
THEN concat(substr(idcard, 1, 6), repeat('*', 4), substr(idcard, 10, 4))
ELSE idcard
END;
3 基于角色的动态脱敏
需求: user_admin角色可查看完整信息
CREATE FUNCTION public.idcard_masking_role(idcard STRING)
RETURNS STRING
AS
CASE
WHEN array_contains(current_roles(), "user_admin")
THEN idcard
ELSE concat(substr(idcard,1,6), '****', substr(idcard,11,4))
END;
完整操作示例
1 初始化环境
CREATE SCHEMA IF NOT EXISTS security_demo;
USE security_demo;
-- 通用掩码函数
CREATE FUNCTION security_demo.ssn_mask(ssn STRING)
RETURNS STRING
AS concat('***-**-', substr(ssn, 8, 4));
CREATE TABLE security_demo.user_data (
name STRING,
ssn STRING MASK security_demo.ssn_mask, -- 建表时直接绑定
phone STRING
);
INSERT INTO security_demo.user_data VALUES('James', '123-45-6789','123456789');
SELECT * FROM security_demo.user_data;
2 创建策略函数
-- 特权角色豁免
CREATE FUNCTION security_demo.admin_ssn_mask(ssn STRING)
RETURNS STRING
AS
CASE
WHEN array_contains(current_roles(), 'user_admin') THEN ssn
ELSE concat('***-**-', substr(ssn,8,4))
END;
3 修改脱敏策略
--去除之前的策略
ALTER TABLE security_demo.user_data CHANGE COLUMN ssn UNSET MASK;
--添加新的策略
ALTER TABLE security_demo.user_data CHANGE COLUMN ssn SET MASK security_demo.admin_ssn_mask;
4 验证效果
普通用户查询:
SELECT * FROM user_data;
-- 输出:John Doe ***-**-6789 138****1234
USER_ADMIN角色查询:
SELECT * FROM user_data;
-- 输出:John Doe 123-45-6789 138****1234