在使用 MySQL 企业版数据脱敏和去标识化之前,请按照 第 8.5.2.1 节 “MySQL 企业版数据脱敏和去标识化组件安装” 中提供的说明进行安装。
要在应用程序中使用 MySQL 企业版数据脱敏和去标识化,请调用适合您要执行的操作的函数。有关详细的函数说明,请参阅 第 8.5.2.4 节 “MySQL 企业版数据脱敏和去标识化组件函数说明”。本节演示如何使用这些函数来执行一些具有代表性的任务。它首先概述了可用的函数,然后给出了一些如何在现实场景中使用这些函数的示例。
MySQL 提供了屏蔽任意字符串的通用屏蔽组件函数,以及屏蔽特定类型值的专用屏蔽函数。
通用屏蔽组件函数
mask_inner()
和 mask_outer()
是通用函数,它们根据字符串中的位置屏蔽任意字符串的各个部分。这两个函数都支持以任何字符集编码的输入字符串。
mask_inner()
屏蔽其字符串参数的内部,保留两端未屏蔽。其他参数指定未屏蔽两端的长度。mysql> SELECT mask_inner('This is a string', 5, 1); +--------------------------------------+ | mask_inner('This is a string', 5, 1) | +--------------------------------------+ | This XXXXXXXXXXg | +--------------------------------------+ mysql> SELECT mask_inner('This is a string', 1, 5); +--------------------------------------+ | mask_inner('This is a string', 1, 5) | +--------------------------------------+ | TXXXXXXXXXXtring | +--------------------------------------+ mysql> SELECT mask_inner("かすみがうら市", 3, 1); +----------------------------------+ | mask_inner("かすみがうら市", 3, 1) | +----------------------------------+ | かすみXXX市 | +----------------------------------+ mysql> SELECT mask_inner("かすみがうら市", 1, 3); +----------------------------------+ | mask_inner("かすみがうら市", 1, 3) | +----------------------------------+ | かXXXうら市 | +----------------------------------+
mask_outer()
执行相反的操作,屏蔽其字符串参数的两端,保留内部未屏蔽。其他参数指定屏蔽两端的长度。mysql> SELECT mask_outer('This is a string', 5, 1); +--------------------------------------+ | mask_outer('This is a string', 5, 1) | +--------------------------------------+ | XXXXXis a strinX | +--------------------------------------+ mysql> SELECT mask_outer('This is a string', 1, 5); +--------------------------------------+ | mask_outer('This is a string', 1, 5) | +--------------------------------------+ | Xhis is a sXXXXX | +--------------------------------------+
默认情况下,mask_inner()
和 mask_outer()
使用 'X'
作为屏蔽字符,但允许使用可选的屏蔽字符参数。
mysql> SELECT mask_inner('This is a string', 5, 1, '*');
+-------------------------------------------+
| mask_inner('This is a string', 5, 1, '*') |
+-------------------------------------------+
| This **********g |
+-------------------------------------------+
mysql> SELECT mask_inner("かすみがうら市", 2, 2, "#");
+---------------------------------------+
| mask_inner("かすみがうら市", 2, 2, "#") |
+---------------------------------------+
| かす###ら市 |
+---------------------------------------+
专用屏蔽组件函数
其他屏蔽函数需要一个表示特定类型值的字符串参数,并对其进行屏蔽以删除标识特征。
此处的示例使用返回适当类型值的随机值生成函数来提供函数参数。有关生成函数的更多信息,请参阅 生成具有特定特征的随机数据。
支付卡主帐号屏蔽。 屏蔽函数提供严格和宽松的主帐号屏蔽。
mask_pan()
屏蔽除最后四位数字以外的所有数字。mysql> SELECT mask_pan(gen_rnd_pan()); +-------------------------+ | mask_pan(gen_rnd_pan()) | +-------------------------+ | XXXXXXXXXXXX2461 | +-------------------------+
mask_pan_relaxed()
类似,但不屏蔽指示发卡机构的前六位数字。mysql> SELECT mask_pan_relaxed(gen_rnd_pan()); +---------------------------------+ | mask_pan_relaxed(gen_rnd_pan()) | +---------------------------------+ | 770630XXXXXX0807 | +---------------------------------+
国际银行帐号屏蔽。 mask_iban()
屏蔽除前两个字母(表示国家/地区)以外的所有数字。
mysql> SELECT mask_iban(gen_rnd_iban());
+---------------------------+
| mask_iban(gen_rnd_iban()) |
+---------------------------+
| ZZ** **** **** **** |
+---------------------------+
通用唯一标识符屏蔽。 mask_uuid()
屏蔽所有有意义的字符。
mysql> SELECT mask_uuid(gen_rnd_uuid());
+--------------------------------------+
| mask_uuid(gen_rnd_uuid()) |
+--------------------------------------+
| ********-****-****-****-************ |
+--------------------------------------+
美国社会安全号码掩码。 mask_ssn()
会掩盖除最后四位数字以外的所有数字
mysql> SELECT mask_ssn(gen_rnd_ssn());
+-------------------------+
| mask_ssn(gen_rnd_ssn()) |
+-------------------------+
| ***-**-1723 |
+-------------------------+
加拿大社会保险号码掩码。 mask_canada_sin()
会掩盖该号码中有意义的数字
mysql> SELECT mask_canada_sin(gen_rnd_canada_sin());
+---------------------------------------+
| mask_canada_sin(gen_rnd_canada_sin()) |
+---------------------------------------+
| XXX-XXX-XXX |
+---------------------------------------+
英国国民保险号码掩码。 mask_uk_nin()
会掩盖除前两位数字以外的所有数字
mysql> SELECT mask_uk_nin(gen_rnd_uk_nin());
+-------------------------------+
| mask_uk_nin(gen_rnd_uk_nin()) |
+-------------------------------+
| ZH******* |
+-------------------------------+
一些组件函数可以生成随机值。这些值可用于测试、模拟等。
gen_range()
返回从给定范围内选择的随机整数
mysql> SELECT gen_range(1, 10);
+------------------+
| gen_range(1, 10) |
+------------------+
| 6 |
+------------------+
gen_rnd_canada_sin()
返回从不用于合法号码的范围内选择的随机号码
mysql> SELECT gen_rnd_canada_sin();
+----------------------+
| gen_rnd_canada_sin() |
+----------------------+
(不显示 gen_rnd_canada_sin()
函数的结果,因为它的返回值只能用于测试目的,而不能用于发布。不能保证该号码没有分配给合法的加拿大 SIN。)
gen_rnd_email()
返回一个随机电子邮件地址,该地址在指定域(以下示例中为 mynet.com
)中包含指定位数的姓名和姓氏部分
mysql> SELECT gen_rnd_email(6, 8, 'mynet.com');
+------------------------------+
| gen_rnd_email(6, 8, 'mynet') |
+------------------------------+
| [email protected] |
+------------------------------+
gen_rnd_iban()
返回从不用于合法号码的范围内选择的号码
mysql> SELECT gen_rnd_iban('XO', 24);
+-------------------------------+
| gen_rnd_iban('XO', 24) |
+-------------------------------+
| XO25 SL7A PGQR B9NN 6IVB RFE8 |
+-------------------------------+
gen_rnd_pan()
返回一个随机的支付卡主帐号
mysql> SELECT gen_rnd_pan();
(不显示 gen_rnd_pan()
函数的结果,因为它的返回值只能用于测试目的,而不能用于发布。不能保证该号码没有分配给合法的支付帐户。)
gen_rnd_ssn()
返回一个随机的美国社会安全号码,其第一部分和第二部分分别从不用于合法号码的范围内选择
mysql> SELECT gen_rnd_ssn();
+---------------+
| gen_rnd_ssn() |
+---------------+
| 912-45-1615 |
+---------------+
gen_rnd_uk_nin()
返回从不用于合法号码的范围内选择的号码
mysql> SELECT gen_rnd_uk_nin();
+------------------+
| gen_rnd_uk_nin() |
+------------------+
(不显示 gen_rnd_uk_nin()
函数的结果,因为它的返回值只能用于测试目的,而不能用于发布。不能保证该号码没有分配给合法的 NIN。)
gen_rnd_us_phone()
返回 555 区号中不用于合法号码的随机美国电话号码
mysql> SELECT gen_rnd_us_phone();
+--------------------+
| gen_rnd_us_phone() |
+--------------------+
| 1-555-747-5627 |
+--------------------+
gen_rnd_uuid()
返回从不用于合法标识符的范围内选择的号码
mysql> SELECT gen_rnd_uuid();
+--------------------------------------+
| gen_rnd_uuid() |
+--------------------------------------+
| 68946384-6880-3150-6889-928076732539 |
+--------------------------------------+
MySQL 企业版数据掩码和去标识化功能允许将字典用作称为术语的随机值的来源。要使用字典,必须先将其添加到 masking_dictionaries
系统表中并为其命名。字典将在组件初始化期间(服务器启动时)从表中读取并加载到缓存中。然后,可以从字典中添加、删除和选择术语,并将其用作随机值或其他值的替换值。
始终使用字典管理函数编辑字典,而不是直接修改表。如果手动操作表,则字典缓存将与表不一致。
有效的 masking_dictionaries
表具有以下特征
管理员在
mysql
模式中创建了masking_dictionaries
系统表,如下所示CREATE TABLE IF NOT EXISTS masking_dictionaries( Dictionary VARCHAR(256) NOT NULL, Term VARCHAR(256) NOT NULL, UNIQUE INDEX dictionary_term_idx (Dictionary, Term), INDEX dictionary_idx (Dictionary) ) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4;
添加和删除术语或删除整个字典需要 MASKING_DICTIONARY_ADMIN 权限。
该表可能包含多个字典及其术语。
任何用户帐户都可以查看字典。如果有足够的查询,则可以检索字典中的所有术语。避免将敏感数据添加到字典表中。
假设名为 DE_cities
的字典包含德国的以下城市名称
Berlin
Munich
Bremen
使用 masking_dictionary_term_add()
分配字典名称和一个术语
mysql> SELECT masking_dictionary_term_add('DE_Cities', 'Berlin');
+----------------------------------------------------+
| masking_dictionary_term_add('DE_Cities', 'Berlin') |
+----------------------------------------------------+
| 1 |
+----------------------------------------------------+
mysql> SELECT masking_dictionary_term_add('DE_Cities', 'Munich');
+----------------------------------------------------+
| masking_dictionary_term_add('DE_Cities', 'Munich') |
+----------------------------------------------------+
| 1 |
+----------------------------------------------------+
mysql> SELECT masking_dictionary_term_add('DE_Cities', 'Bremen');
+----------------------------------------------------+
| masking_dictionary_term_add('DE_Cities', 'Bremen') |
+----------------------------------------------------+
| 1 |
+----------------------------------------------------+
还假设名为 US_Cities
的字典包含美国的以下城市名称
Houston
Phoenix
Detroit
mysql> SELECT masking_dictionary_term_add('US_Cities', 'Houston');
+-----------------------------------------------------+
| masking_dictionary_term_add('US_Cities', 'Houston') |
+-----------------------------------------------------+
| 1 |
+-----------------------------------------------------+
mysql> SELECT masking_dictionary_term_add('US_Cities', 'Phoenix');
+-----------------------------------------------------+
| masking_dictionary_term_add('US_Cities', 'Phoenix') |
+-----------------------------------------------------+
| 1 |
+-----------------------------------------------------+
mysql> SELECT masking_dictionary_term_add('US_Cities', 'Detroit');
+-----------------------------------------------------+
| masking_dictionary_term_add('US_Cities', 'Detroit') |
+-----------------------------------------------------+
| 1 |
+-----------------------------------------------------+
要从字典中选择随机术语,请使用 gen_dictionary()
mysql> SELECT gen_dictionary('DE_Cities');
+-----------------------------+
| gen_dictionary('DE_Cities') |
+-----------------------------+
| Berlin |
+-----------------------------+
mysql> SELECT gen_dictionary('US_Cities');
+-----------------------------+
| gen_dictionary('US_Cities') |
+-----------------------------+
| Phoenix |
+-----------------------------+
要从多个字典中选择随机术语,请随机选择其中一个字典,然后从中选择一个术语
mysql> SELECT gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities'));
+---------------------------------------------------------------+
| gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities')) |
+---------------------------------------------------------------+
| Detroit |
+---------------------------------------------------------------+
mysql> SELECT gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities'));
+---------------------------------------------------------------+
| gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities')) |
+---------------------------------------------------------------+
| Bremen |
+---------------------------------------------------------------+
gen_blocklist()
函数允许用一个字典中的术语替换另一个字典中的术语,从而实现通过替换进行掩码。其参数是要替换的术语、该术语所在的字典以及从中选择替换术语的字典。例如,要用美国城市替换德国城市,反之亦然,请使用 gen_blocklist()
,如下所示
mysql> SELECT gen_blocklist('Munich', 'DE_Cities', 'US_Cities');
+---------------------------------------------------+
| gen_blocklist('Munich', 'DE_Cities', 'US_Cities') |
+---------------------------------------------------+
| Houston |
+---------------------------------------------------+
mysql> SELECT gen_blocklist('El Paso', 'US_Cities', 'DE_Cities');
+----------------------------------------------------+
| gen_blocklist('El Paso', 'US_Cities', 'DE_Cities') |
+----------------------------------------------------+
| Bremen |
+----------------------------------------------------+
如果要替换的术语不在第一个字典中,则 gen_blocklist()
将原样返回该术语
mysql> SELECT gen_blocklist('Moscow', 'DE_Cities', 'US_Cities');
+---------------------------------------------------+
| gen_blocklist('Moscow', 'DE_Cities', 'US_Cities') |
+---------------------------------------------------+
| Moscow |
+---------------------------------------------------+
在客户服务呼叫中心,一种常见的身份验证技术是要求客户提供其社会安全号码 (SSN) 的最后四位数字。例如,一位客户可能会说她叫 Joanna Bond,她的 SSN 的最后四位数字是 0007
。
假设包含客户记录的 customer
表具有以下列
id
:客户 ID 号。first_name
:客户名字。last_name
:客户姓氏。ssn
:客户社会安全号码。
例如,该表可以定义如下
CREATE TABLE customer
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(40),
last_name VARCHAR(40),
ssn VARCHAR(11)
);
客户服务代表用来检查客户 SSN 的应用程序可能会执行如下查询
mysql> SELECT id, ssn
mysql> FROM customer
mysql> WHERE first_name = 'Joanna' AND last_name = 'Bond';
+-----+-------------+
| id | ssn |
+-----+-------------+
| 786 | 906-39-0007 |
+-----+-------------+
但是,这会将 SSN 暴露给客户服务代表,而客户服务代表除了最后四位数字外,不需要看到任何内容。相反,应用程序可以使用以下查询仅显示掩码后的 SSN
mysql> SELECT id, mask_ssn(CONVERT(ssn USING binary)) AS masked_ssn
mysql> FROM customer
mysql> WHERE first_name = 'Joanna' AND last_name = 'Bond';
+-----+-------------+
| id | masked_ssn |
+-----+-------------+
| 786 | ***-**-0007 |
+-----+-------------+
现在,代表只能看到必要的内容,并且客户隐私得到保护。
为什么要将 CONVERT()
函数用于 mask_ssn()
的参数?因为 mask_ssn()
需要长度为 11 的参数。因此,即使 ssn
定义为 VARCHAR(11)
,如果 ssn
列具有多字节字符集,则在传递给可加载函数时,它可能看起来比 11 个字节长,并且在记录错误的同时返回 NULL
。将值转换为二进制字符串可确保函数看到长度为 11 的参数。
当字符串参数没有单字节字符集时,其他数据掩码函数可能也需要类似的技术。
如果来自表的掩码数据用于多个查询,则定义一个生成掩码数据的视图可能会很方便。这样,应用程序就可以从视图中进行选择,而无需在单个查询中执行掩码。
例如,可以像这样定义上一节中 customer
表的掩码视图
CREATE VIEW masked_customer AS
SELECT id, first_name, last_name,
mask_ssn(CONVERT(ssn USING binary)) AS masked_ssn
FROM customer;
然后,查找客户的查询变得更简单,但仍然返回掩码数据
mysql> SELECT id, masked_ssn
mysql> FROM masked_customer
mysql> WHERE first_name = 'Joanna' AND last_name = 'Bond';
+-----+-------------+
| id | masked_ssn |
+-----+-------------+
| 786 | ***-**-0007 |
+-----+-------------+