适用于:Azure SQL 数据库
本文将向您展示如何使用REGEXP_REPLACE掩蔽函数在 Azure SQL 数据库 中定义模式驱动的动态数据掩蔽规则。 基于正则表达式的掩码支持对可变长度的字符串数据进行掩码处理,并保留内置掩码无法实现的特定片段。
Important
基于正则表达式的动态数据掩码现已在 Azure SQL 数据库 中提供公开预览。 预览功能以“现状”形式提供,不包含在服务水平协议和有限保修之外。 仅在非生产环境中使用此功能。 有关详细信息,请参阅适用于 Azure 预览版的补充使用条款。
概述
Azure SQL 数据库中的动态数据掩蔽(DDM)在查询结果中动态隐藏敏感数据,在数据发送到应用程序之前。 此功能减少了敏感信息的意外暴露,并消除了在应用代码中添加掩蔽逻辑的需求。
DDM 允许数据库管理员和开发者在数据库中中心定义敏感列的遮蔽规则。 非特权用户看到的数值被混淆,而实际数据则保持在存储中。
内置遮罩功能的局限性
Azure SQL 数据库 提供了多个内置的遮蔽函数:default()、 email()random()partial()datetime()和 。 这些函数中的大多数都采用了固定模式,既无法自定义,也无法灵活处理可变长度的数据。
例如,对于像 email() 这样的电子邮件地址,内置的 aXXX@xxxx.com 掩码始终会生成类似 alice.johnson@example.com 的格式。 该掩码只显示用户名的首字母,并遮蔽域名。 当你需要为业务流程保留域名时,固定输出并不实用。
什么是基于正则表达式的掩码处理?
基于正则表达式的 DDM 将 REGEXP_REPLACE 引入为一种新的掩码函数。 通过使用此功能,你可以为字符串数据(如电话号码、电子邮件地址和识别号)创建自定义的模式驱动掩码。
正则表达式允许你精确定义哪些子字符串需要揭示或遮蔽。 内置函数无法表达这种可变长度的模式。 当你处理电子邮件、电话号码或标识符等结构化数据模式时,这一功能非常有用。 在这种情况下,你通常需要保留特定的可见片段,同时对敏感部分进行掩盖,而内置遮罩对你的业务流程来说过于僵硬。
注释
- 权限模式保持不变。 此增强不引入新的权限。
- 你只能在 T-SQL 中配置正则表达式掩码。 Azure门户在本版本中不支持正则表达式掩码配置。
Syntax
在创建表时应用正则表达式掩码:
column_name <data_type> MASKED WITH (FUNCTION = 'REGEXP_REPLACE("<pattern_expression>", "<string_replacement>")')
向现有列添加正则表达式掩码:
ALTER TABLE <schema_name>.<table_name>
ALTER COLUMN <column_name>
ADD MASKED WITH (FUNCTION = 'REGEXP_REPLACE("<pattern_expression>", "<string_replacement>")');
Arguments
pattern_expression
正则表达式用来对列值进行评估。 最大长度为8,000字节。
string_replacement
应用于 pattern_expression 的每个匹配项的替换字符串。
注释
当你用作 REGEXP_REPLACE 掩蔽函数时,只有 pattern_expression 和 string_replacement 参数起作用。 原生的 T-SQL REGEXP_REPLACE 函数也支持 start、 occurnce 和 flags 参数,但用作掩蔽函数时无法覆盖它们。 固定值分别为 start = 1、occurrence = 0(替换所有匹配项),以及 flags = 'c'(区分大小写)。
REGEXP_REPLACE 掩码函数支持数据类型为 char、nchar、varchar 或 nvarchar 的列,以及大小不超过 2 MB 的 LOB 类型(varchar(max) 和 nvarchar(max))。
教程:配置基于正则表达式的动态数据掩蔽
以下教程将教你如何创建正则表达式掩码、插入样本数据,以及验证不同用户的遮蔽输出与未遮蔽输出。
步骤 1:创建包含正则表达式掩码的表
以下语句创建了一个 CustomerDetails 表,其中包含两个经过正则表达式掩码处理的列:
-
电话号码掩码:保留国家/地区代码(例如
+1、+44、+91),并将其余数字替换为xxxx。 这样可以保留国家代码作为上下文。 -
电子邮件掩码:将用户名部分(之前
@)替换为*****,同时保留域名。 例如,alice.johnson@example.com将变为*****@example.com。
-- Drop the CustomerDetails table if it exists
DROP TABLE IF EXISTS Data.CustomerDetails;
CREATE TABLE Data.CustomerDetails (
ID INT IDENTITY(1,1) PRIMARY KEY,
Name varchar(30),
Phone_Number varchar(30)
MASKED WITH (FUNCTION = 'REGEXP_REPLACE(
"(\+\d{1,3})(?:[ -.]?\d){7,14}",
"(\1)-xxxx")'),
Email varchar(255)
MASKED WITH (FUNCTION = 'REGEXP_REPLACE(
"([a-zA-Z0-9._%+-]+)(@+)([a-zA-Z0-9.-]+)(\.)(\w)",
"*****\2\3\4\5")')
);
步骤2:插入样本数据
INSERT INTO Data.CustomerDetails (Name, Phone_Number, Email) VALUES
('Alice Johnson', '+1 202-555-0123', 'alice.johnson@example.com'),
('Bob Smith', '+1 415-555-0198', 'bob.smith@contoso.com'),
('Oliver Bennett', '+44 7700 900123', 'oliver.bennett@example.co.uk'),
('Amelia Thompson', '+44 7700 900456', 'amelia.thompson@example.co.uk'),
('Rajeev Mehra', '+91 90000 12345', 'rajeev.mehra@adventure-works.net'),
('John Miller', '+91 98888 45678', 'jon.miller@contoso.net'),
('Lukas Mueller', '+49 151 23456789', 'lukas.mueller@example.de'),
('Daniel Tan', '+65 8123 4567', 'daniel.tan@example.sg'),
('Hiroshi Tanaka', '+81 90 1234 5678', 'hiroshi.tanaka@example.jp');
步骤3:作为特权用户查询
拥有 sysadmin、 db_owner或明确 UNMASK 权限的用户始终能看到实际数据。
-- As sysadmin or db_owner, you see the real data
SELECT * FROM Data.CustomerDetails;
预期结果:所有电话号码和电子邮件均完整显示(例如, +1 202-555-0123, alice.johnson@example.com)。
步骤4:作为非特权用户查询
创建一个测试用户,无需 UNMASK 授权并查询该表。
-- Create a test user without UNMASK permission
CREATE USER SupportEngineer WITHOUT LOGIN;
-- Grant SELECT permission on CustomerDetails to SupportEngineer
GRANT SELECT ON Data.CustomerDetails TO SupportEngineer;
-- Query the table as the nonprivileged user
EXECUTE AS USER = 'SupportEngineer';
SELECT * FROM Data.CustomerDetails;
REVERT;
预期结果:电话号码仅显示国家代码(例如, (+1)-xxxx),电子邮件隐藏用户名(例如, *****@example.com)。
步骤 5:授予 UNMASK 权限并重新查询
授予 UNMASK后,同一用户现在看到完整的未掩码值。 这展示了DDM基于许可的访问控制的工作原理。
-- Grant UNMASK permission to the test user
GRANT UNMASK ON Data.CustomerDetails TO SupportEngineer;
-- Re-run the query as the same user - now sees unmasked data
EXECUTE AS USER = 'SupportEngineer';
SELECT * FROM Data.CustomerDetails;
REVERT;
向现有列添加正则表达式掩码
要向现有列添加正则表达式掩码,请使用 ALTER TABLE:
ALTER TABLE Data.CustomerDetails
ALTER COLUMN Phone_Number
ADD MASKED WITH (FUNCTION = 'REGEXP_REPLACE(
"(\+\d{1,3})(?:[ -.]?\d){7,14}",
"(\1)-xxxx")');
通过元数据验证掩蔽策略
使用 sys.masked_columns 系统视图检查已配置的掩码。 此视图包含 REGEXP_REPLACE 遮罩定义。
SELECT c.name,
tbl.name AS table_name,
c.is_masked,
c.masking_function
FROM sys.masked_columns AS c
JOIN sys.tables AS tbl
ON c.[object_id] = tbl.[object_id]
WHERE is_masked = 1;
Considerations
- 正则表达式掩码依赖于模式。 在应用到生产列之前,先验证代表性数据上的正则表达式模式。
- 未匹配的数值保持不被掩盖。 未匹配模式会将原始数据返回给非特权用户,这可能会暴露敏感信息。
- 用具代表性的数据彻底测试。 涵盖诸如空值、空字符串和非典型格式等正则表达式可能捕捉不到的边缘情况。
- 预览期间请在非生产环境中使用。 在将此功能用于生产工作负载之前,请务必进行充分验证。