龙空技术网

SaaS 多租户架构持久层的设计(四)SQL数据库的数据隔离

芝士Flash 261

前言:

眼前姐妹们对“oracleschemabinding”大概比较关注,大家都想要了解一些“oracleschemabinding”的相关资讯。那么小编在网络上网罗了一些有关“oracleschemabinding””的相关资讯,希望兄弟们能喜欢,我们一起来了解一下吧!

之前有朋友提到数据的隔离,这里先介绍一种传统SQL的隔离:RLS的隔离。

1. 应用层:在SESSION_CONTEXT中设置 TenantId

首先,使用数据库客户端库的数据相关路由 API 连接到分片数据库。应用程序仍必须告知数据库哪个 TenantId 正在使用连接。TenantId 告知 RLS 安全策略哪些行必须筛选为属于其他租户。将当前租户 ID 存储在连接的SESSION_CONTEXT中。

SESSION_CONTEXT的替代方法是使用CONTEXT_INFO。但SESSION_CONTEXT是更好的选择。SESSION_CONTEXT更易于使用,但它默认返回 NULL,并且支持键值对。zai

在返回connection前把SESSION_CONTEXT附加到connection上:

  cmd.CommandText =            @"exec sp_set_session_context                @key=N'TenantId', @value=@shardingKey";        cmd.Parameters.AddWithValue("@shardingKey", shardingKey);        cmd.ExecuteNonQuery();
2. 数据层:创建行级别安全策略创建安全策略以筛选每个租户可以访问的行

现在,应用程序在查询之前使用当前 TenantId 设置SESSION_CONTEXT,RLS 安全策略可以筛选查询并排除具有不同 TenantId 的行。

RLS 在 Transact-SQL 中实现。用户定义的函数定义访问逻辑,安全策略将此函数绑定到任意数量的表。对于此项目:

该函数验证应用程序是否已连接到数据库,以及存储在SESSION_CONTEXT中的 TenantId 是否与给定行的 TenantId 匹配。应用程序已连接,而不是其他某个 SQL 用户。筛选器谓词允许满足 TenantId 筛选器的行通过选择、更新和删除查询。BLOCK 谓词可防止未通过筛选器的行入或更新。如果尚未设置SESSION_CONTEXT,则该函数返回 NULL,并且没有行可见或无法插入。

若要在所有分片上启用 RLS,可以看一下此 T-SQL。创建一个policy 去过滤数据。

CREATE SCHEMA rls; -- Separate schema to organize RLS objects.GOCREATE FUNCTION rls.fn_tenantAccessPredicate(@TenantId int)    RETURNS TABLE    WITH SCHEMABINDINGAS    RETURN SELECT 1 AS fn_accessResult        -- Use the user in your application's connection string.        -- Here we use 'dbo' only for demo purposes!        WHERE DATABASE_PRINCIPAL_ID() = DATABASE_PRINCIPAL_ID('dbo')        AND CAST(SESSION_CONTEXT(N'TenantId') AS int) = @TenantId;GOCREATE SECURITY POLICY rls.tenantAccessPolicy    ADD FILTER PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.Blogs,    ADD BLOCK  PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.Blogs,    ADD FILTER PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.Posts,    ADD BLOCK  PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.Posts;GO

如果稍后添加新表,请更改安全策略以在新表上添加 FILTER 和 BLOCK 谓词。

ALTER SECURITY POLICY rls.tenantAccessPolicy    ADD FILTER PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.MyNewTable,    ADD BLOCK  PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.MyNewTable;GO
添加默认约束以自动填充插入的租户 ID

可以在每个表上放置默认约束,以便在插入行时使用当前存储在SESSION_CONTEXT中的值自动填充 TenantId。下面是一个示例。

-- Create default constraints to auto-populate TenantId with the-- value of SESSION_CONTEXT for inserts.ALTER TABLE Blogs    ADD CONSTRAINT df_TenantId_Blogs    DEFAULT CAST(SESSION_CONTEXT(N'TenantId') AS int) FOR TenantId;GOALTER TABLE Posts    ADD CONSTRAINT df_TenantId_Posts    DEFAULT CAST(SESSION_CONTEXT(N'TenantId') AS int) FOR TenantId;GO

标签: #oracleschemabinding