如何将动态数据屏蔽与 FOR XML PATH 和子查询一起使用

How to use Dynamic Data Masking with FOR XML PATH and subqueries

我正在尝试从数据库生成 XML 并使用动态数据屏蔽来隐藏敏感信息,但是当我执行生成 XML 的存储过程时,用户应该只查看屏蔽数据,完成的 XML 缺少子查询的输出,只生成 <masked /> 而不是通常的标签和该标签的内容。当我 运行 作为我的常规数据库用户的存储过程时,我得到了我需要的 XML-结果。

我已经尝试更改我的“蒙面数据库用户”的权限,但我无法解决问题。

这是我的存储过程的内容:

    WITH XMLNAMESPACES (DEFAULT 'urn:svsys:export:user')
    SELECT
        u.userId
       ,u.identityNumber
       ,u.firstName
       ,u.lastName
       ,(SELECT
                ur.role
            FROM dbo.UserRole ur
            WHERE ur.userId = u.id
            FOR XML PATH (''), ROOT ('userRoles'), TYPE, ELEMENTS)
    FROM dbo.[User] u
    INNER JOIN dbo.LegalCareUnit lcu
        ON u.legalCareUnitId = lcu.id
    WHERE lcu.legalCareUnitId = @LegalCareUnitId
    FOR XML PATH ('user'), ROOT ('users')

以及由我的 常规数据库用户执行时的输出示例,即。没有动态数据屏蔽:

<users xmlns="urn:svsys:export:user">
  <user>
    <userId>2</userId>
    <identityNumber>111</identityNumber>
    <firstName>Paddy</firstName>
    <lastName>Smith</lastName>
    <userRoles xmlns="urn:svsys:export:user">
      <role>testRole</role>
    </userRoles>
  </user>
</users>

以及 XML 以我的 屏蔽数据库用户(使用动态数据屏蔽)执行时的外观:

<users xmlns="urn:svsys:export:user">
  <user>
    <userId>2</userId>
    <identityNumber>xxx</identityNumber>
    <firstName>Paxxx</firstName>
    <lastName>Smxxx</lastName>
    <masked xmlns="" />
  </user>
</users>

当以我的 masked 数据库用户(使用动态数据屏蔽):

执行时,我想得到什么
<users xmlns="urn:svsys:export:user">
  <user>
    <userId>2</userId>
    <identityNumber>xxx</identityNumber>
    <firstName>Paxxx</firstName>
    <lastName>Smxxx</lastName>
    <userRoles xmlns="urn:svsys:export:user">
      <role>texxxxxx</role>
    </userRoles>
  </user>
</users>

如您所见,我第一个示例中的标签 <userRoles xmlns="urn:svsys:export:user"> 在第二个示例中被 <masked xmlns="" /> 替换。

知道如何在子标签 <role> 中获取带有屏蔽信息的标签 <userRoles> 吗?

测试设置

CREATE TABLE dbo.[TestUser]
(
    id INT PRIMARY KEY IDENTITY(1,1),
    userId INT NOT NULL,
    identityNumber NVARCHAR(50) MASKED WITH (FUNCTION = 'partial(4, "0101", 0)')  NOT NULL,
    firstName NVARCHAR(50) MASKED WITH (FUNCTION = 'partial(2, "xxxxxxxxx", 0)') NOT NULL,
    lastName NVARCHAR(50) MASKED WITH (FUNCTION = 'partial(2, "xxxxxxxxx", 0)') NOT NULL
)


CREATE TABLE dbo.TestUserRole
(
    id INT PRIMARY KEY IDENTITY(1,1),
    userId INT NOT NULL,
    userRole NVARCHAR(50) MASKED WITH (FUNCTION = 'partial(2, "xxxxxxxxx", 0)') NOT NULL
)

ALTER TABLE [dbo].[TestUserRole]  WITH CHECK ADD CONSTRAINT [FK_TestUser_UserRole] FOREIGN KEY([userId])
REFERENCES [dbo].[User] ([id])

SET IDENTITY_INSERT TestUser ON

INSERT INTO TestUser (id, userId, identityNumber, firstName, lastName)
    VALUES (1, 200, N'19520102', N'Paddy', N'Smith'),
    (2, 300, N'19500609', N'Trevor', N'Bolder'),
    (3, 400, N'19460526', N'Mick', N'Ronson')

SET IDENTITY_INSERT TestUser OFF

INSERT INTO TestUserRole (userId, userRole)
    VALUES (1, N'Roadie'),
    (2, N'Bassist'),
    (3, N'Guitarist'),
    (3, N'Pianist')
GO

CREATE PROCEDURE [dbo].TestGetUserRecordXml
AS
    WITH XMLNAMESPACES (DEFAULT 'urn:svsys:export:user')
    SELECT
        u.userId
       ,u.identityNumber
       ,u.firstName
       ,u.lastName
       ,(SELECT
                ur.userRole
            FROM dbo.TestUserRole ur
            WHERE ur.userId = u.id
            FOR XML PATH (''), ROOT ('userRoles'), TYPE, ELEMENTS)
    FROM dbo.TestUser u
    FOR XML PATH ('user'), ROOT ('users')
GO

CREATE USER [UserForMaskedData] WITHOUT LOGIN;
GRANT EXECUTE ON SCHEMA::dbo TO UserForMaskedData;
GRANT SELECT ON SCHEMA::dbo TO UserForMaskedData;

从 Microsoft Docs (https://docs.microsoft.com/en-us/answers/questions/526979/generating-xml-from-sql-with-dynamic-data-masking.html) 的 Erland Sommarskog 那里得到答案

为了使掩码在子查询中正常工作,必须将其放入临时 table,因此存储过程应如下所示:

SELECT * INTO #testis FROM TestUserRole;
WITH XMLNAMESPACES (DEFAULT 'urn:svsys:export:user')
SELECT
    u.userId
   ,u.identityNumber
   ,u.firstName
   ,u.lastName
   ,(SELECT
            ur.userRole
        FROM #testis ur
        WHERE ur.userId = u.id
        FOR XML PATH (''), ROOT ('userRoles'), TYPE, ELEMENTS)
FROM dbo.TestUser u
FOR XML PATH ('user'), ROOT ('users')

当以用户 UserForMaskedData 身份执行存储过程时,我得到了我想要的结果:

<users xmlns="urn:svsys:export:user">
  <user>
    <userId>200</userId>
    <identityNumber>19520101</identityNumber>
    <firstName>Paxxxxxxxxx</firstName>
    <lastName>Smxxxxxxxxx</lastName>
    <userRoles xmlns="urn:svsys:export:user">
      <userRole>Roxxxxxxxxx</userRole>
    </userRoles>
  </user>
  <user>
    <userId>300</userId>
    <identityNumber>19500101</identityNumber>
    <firstName>Trxxxxxxxxx</firstName>
    <lastName>Boxxxxxxxxx</lastName>
    <userRoles xmlns="urn:svsys:export:user">
      <userRole>Baxxxxxxxxx</userRole>
    </userRoles>
  </user>
  <user>
    <userId>400</userId>
    <identityNumber>19460101</identityNumber>
    <firstName>Mixxxxxxxxx</firstName>
    <lastName>Roxxxxxxxxx</lastName>
    <userRoles xmlns="urn:svsys:export:user">
      <userRole>Guxxxxxxxxx</userRole>
      <userRole>Pixxxxxxxxx</userRole>
    </userRoles>
  </user>
</users>