8.5.2.2 使用 MySQL 企业数据屏蔽和去标识化组件
在使用 MySQL Enterprise Data Masking and De-Identification 之前,按照第8.5.2.1节,“MySQL Enterprise Data Masking and De-Identification 组件安装”中的说明进行安装。
要在应用程序中使用 MySQL Enterprise Data Masking and De-Identification,调用适用于您想要执行操作的函数。详细函数描述,请见第8.5.2.4节,“MySQL Enterprise Data Masking and De-Identification 组件函数描述”。该节展示了如何使用函数来完成一些示例任务。首先,介绍可用的函数,然后是函数在实际应用中的示例:
MySQL 提供了通用掩码组件函数,可以掩码任意字符串,和特殊掩码函数可以掩码特定类型的值。
General-Purpose Masking Component Functions
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, "#") |
+---------------------------------------+
| かす###ら市 |
+---------------------------------------+
Special-Purpose Masking Component Functions
其他掩码函数预期一个字符串参数,表示特定类型的值,并将其mask以删除识别特征。
以下示例使用随机值生成函数来提供函数参数。关于生成函数的更多信息,请参见根据特定特征生成随机数据。
付款卡主账户号掩码 掩码函数提供严格和放松的主账户号掩码。
-
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** **** **** **** |
+---------------------------+
通用唯一标识符masking. mask_uuid()
将所有有意义的字符mask:
mysql> SELECT mask_uuid(gen_rnd_uuid());
+--------------------------------------+
| mask_uuid(gen_rnd_uuid()) |
+--------------------------------------+
| ********-****-****-****-************ |
+--------------------------------------+
美国社会安全号码masking. mask_ssn()
将除了最后四位数字外的所有数字mask:
mysql> SELECT mask_ssn(gen_rnd_ssn());
+-------------------------+
| mask_ssn(gen_rnd_ssn()) |
+-------------------------+
| ***-**-1723 |
+-------------------------+
加拿大社会保险号码masking. mask_canada_sin()
将有意义的数字mask:
mysql> SELECT mask_canada_sin(gen_rnd_canada_sin());
+---------------------------------------+
| mask_canada_sin(gen_rnd_canada_sin()) |
+---------------------------------------+
| XXX-XXX-XXX |
+---------------------------------------+
英国国民保险号码masking. mask_uk_nin()
将除了第一两个数字外的所有数字mask:
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()
函数结果只能用于测试目的,不可用于出版。不能保证该号码不被分配给合法加拿大社会保险号。)
gen_rnd_email()
返回指定域名(例如:mynet.com
)中随机生成的电子邮件地址,包括名称和姓氏部分的指定数字个数:
mysql> SELECT gen_rnd_email(6, 8, 'mynet.com');
+------------------------------+
| gen_rnd_email(6, 8, 'mynet') |
+------------------------------+
| ayxnqu.xmkpvvyr@mynet.com |
+------------------------------+
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给客户服务代表,代表无需看到除了最后四位数字以外的任何内容。相反,应用程序可以使用这个查询来显示只masked 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个字符的参数。
类似技术也可能用于其他数据masking函数,当字符串参数不具有单字节字符集时。
如果从表中使用掩码数据进行多个查询,定义一个生成掩码数据的视图可能会很方便。这样应用程序可以从视图中选择,而不需要在单独查询中执行掩码操作。
例如,可以像之前那节中的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 |
+-----+-------------+