在SQL Server安全系列专题月报分享中,咱们已经分享了:如何使用对称密钥实现SQL Server列加密技术、使用非对称密钥加密方式实现SQL Server列加密、使用混合密钥实现SQL Server列加密技术、列加密技术带来的查询性能问题以及相应解决方案和行级别安全解决方案这五篇文章,文章详情能够参见往期月报。本期月报咱们分享使用SQL Server 2016 dynamic data masking实现隐私数据列的打码技术最佳实践。数据库
在平日的生活中,咱们或多或少都经历过广告推销、电话诈骗,不厌其烦,甚至更为严重到银行卡号泄漏、身份证号泄漏等更为严重的状况。这个时候,因而咱们就在想有没有技术手段来尽可能或最大限度的保护咱们隐私数据安全呢?答案是确定的,SQL Server 2016版本首次引入了dynamic data masking来实现隐私数据列的打码技术,让咱们一块儿来看看如何实现相似于手机号、身份证号、驾照号等隐私数据打码技术。安全
数据列打码技术的自己咱们并不陌生,就是将一些比较私密的数据信息隐藏起来,仅开放给有较高权限的用户查看完整数据。打码技术自己并不会对数据作任何的加密、解密等操做。严格意义上讲,数据打码不是一个完整的数据安全解决方案,可是它能够做为安全策略中重要的一环来有效避免用户隐私数据列的泄漏。让咱们一块儿来看看在SQL Server 2016 dynamic data masking是如何实现的。函数
建立测试数据库性能
为了测试方便,咱们专门建立了测试数据库TestDb。测试
--Step 1 - Create MSSQL sample database USE master GO IF DB_ID('TestDb') IS NULL CREATE DATABASE [TestDb]; GO
建立测试表加密
首先,咱们建立一张常规表CustomerInfo,来存放客户信息,其中,CustomerPhone列为用户隐私数据,存放了用户的手机号码。spa
--Step 2 - Create Test Table, init records USE [TestDb] GO IF OBJECT_ID('dbo.CustomerInfo', 'U') IS NOT NULL DROP TABLE dbo.CustomerInfo CREATE TABLE dbo.CustomerInfo ( CustomerId INT IDENTITY(10000,1) NOT NULL PRIMARY KEY, CustomerName VARCHAR(100) NOT NULL, CustomerPhone CHAR(11) NOT NULL ); -- Init Table INSERT INTO dbo.CustomerInfo VALUES ('CustomerA','13402872514') ,('CustomerB','13880674722') ,('CustomerC','13487759293') GO
建立测试用户code
为了方便观察和检查测试效果,咱们建立一个测试帐号DemoUser。ci
-- Step3: Create a DemoUser to test USE [TestDb] GO CREATE USER DemoUser WITHOUT LOGIN; GRANT SELECT ON dbo.CustomerInfo TO DemoUser; GO EXECUTE AS USER = 'DemoUser'; -- Verify data SELECT * FROM dbo.CustomerInfo REVERT
常规状况下,测试帐号,能够清清楚楚,明明白白看到用户全部数据,包含客户手机号这种关键的隐私数据。若是,这个用户有不轨之心是很是容易将这些信息泄漏、导出的,安全风险较大。rem
客户手机号打码
因而,咱们想,若是可以将客户隐私数据,好比,电话号码(身份证号码、银行卡号等)打码的话,那么测试帐号就没法查看到用户完整的数据信息了。打码方法以下:
-- Step4: Alter phone column add data mask USE [TestDb] GO ALTER TABLE dbo.CustomerInfo ALTER COLUMN CustomerPhone ADD MASKED WITH(FUNCTION='partial(3, "****", 4)');
因为CustomerPhone是11位数字,咱们使用partial方法打码隐藏中间四位,打码符号使用星号,保留前三位和后四位数数字便可。
查询打码列
打码完毕,咱们使用系统试图查看打码列和打码函数:
-- Step5\. Query system view to check data mask SELECT db_name() as database_name, SCHEMA_NAME(schema_id) AS schema_name, tbl.name as table_name, c.name as column_name, c.is_masked, c.masking_function FROM sys.masked_columns AS c WITH (NOLOCK) INNER JOIN sys.tables AS tbl WITH(NOLOCK) ON c.[object_id] = tbl.[object_id] WHERE c.is_masked = 1 AND tbl.name = 'CustomerInfo';
从结果能够看到咱们已经将表TestDb.dbo.CustomerInfo中字段CustomerPhone打码,打码函数为partial(3, "**", 4),结果展现以下所示:
测试用户查看数据
打码完毕后,再次使用DemoUser测试帐号查看打码后的数据:
-- Step6: Demo user to query and verify data USE [TestDb] GO EXECUTE AS USER = 'DemoUser'; -- Verify data SELECT * FROM dbo.CustomerInfo REVERT
从查询结果展现来看,客户手机号码列中间四位已经成功打码了,测试帐号已经没法获取到完整的客户电话号码了。
修改打码符号
有时候,有的人会说,我不喜欢星号,可否换个打码姿式,我更喜欢使用字母X。只要你喜欢,随便切换,方法以下:
-- Step7: What if I want to change the mask sign from * to X USE [TestDb] GO ALTER TABLE dbo.CustomerInfo ALTER COLUMN CustomerPhone CHAR(11) MASKED WITH(FUNCTION='partial(3, "XXXX", 4)');
如今打码符号变成了X,展现以下:
新增隐私打码列
如今咱们须要增长一个新的列,用来存放用户email地址,也请同时打码。很是简单,新增列的时候使用email打码函数便可,以下所示:
-- Step8: and I want to add a new email mask column ALTER TABLE dbo.CustomerInfo ADD Email varchar(100) MASKED WITH (FUNCTION = 'email()') NOT NULL DEFAULT('demo.user@test.com')
查询打码列特定值
有的人可能会问,手机号码被打码了,这个列会影响个人WHERE语句查询吗?固然不会,由于data mask技术自己并无对数据作任何修改,只是在展现的时候,打码隐藏掉部分信息而已。
-- Step9: Demo user to query the specified phone customer info USE [TestDb] GO EXECUTE AS USER = 'DemoUser'; -- Verify data SELECT * FROM dbo.CustomerInfo WHERE CustomerPhone = '13880674722' REVERT
查询结果展现,手机号码和email地址始终被打码。
拷贝存在打码列的表
咱们说data mask技术并无加密、修改数据自己。到目前为止,测试帐号DemoUser已经没法获取到客人的关键隐私数据了,那么他可以将用户数据Copy、导出吗?让咱们作一个简单的测试,DemoUser将表CustomerInfo复制到一个新表CustomerInfo_copied中:
-- Step10: Ops, if I copy a new table from the data masked table, I can't get the unmasked data now. USE [TestDb] GO GRANT CREATE TABLE TO DemoUser; GRANT ALTER ON SCHEMA::dbo TO DemoUser; EXECUTE AS USER = 'DemoUser'; -- Verify data SELECT * INTO dbo.CustomerInfo_copied FROM dbo.CustomerInfo REVERT GRANT SELECT ON dbo.CustomerInfo_copied TO DemoUser; EXECUTE AS USER = 'DemoUser'; SELECT * FROM dbo.CustomerInfo_copied REVERT
DemoUser复制了客户信息数据到新表后,查看新表中的数据,依然是被打码的,测试用户没法导出、复制客人的隐私数据。达到了安全策略保护客户隐私数据的目的,展现结果以下:
我想要在无码的世界
若是有一天DemoUser成了高权限用户,确实须要查看客户隐私数据列,这个时候,咱们能够给予测试帐号unmask的权限,他就能够看到完整的客户数据了。方法以下:
-- Step 11: But, how can demo user to query the unmasked data? USE TestDB GO GRANT UNMASK TO DemoUser; EXECUTE AS USER = 'DemoUser'; SELECT * FROM dbo.CustomerInfo; REVERT; -- Removing the UNMASK permission REVOKE UNMASK TO DemoUser;
此时,DemoUser查询到的数据,是很是完整的客人数据。
删掉打码
删除打码,让全部用户回归无码的世界。
-- Step 12: all the demos have been done, it's time to drop the mask. USE TestDB GO ALTER TABLE dbo.CustomerInfo ALTER COLUMN CustomerPhone DROP MASKED;
本期月报咱们分享了使用SQL Server 2016引入的新特性dynamic data masking实现客户数据打码技术,防止未受权用户查看、导出用户关键隐私数据,最大限度保证用户数据安全性。
本文为云栖社区原创内容,未经容许不得转载。