说明
用于 NestJS 和 TypeORM 的行级安全实用软件包.
此解决方案无法通过多个连接到数据库(例如:一个连接/租户)来实现. 相反,这一解决方案通过应用RLS数据库政策来发挥作用,如以下所述: 这篇博客文章 (在 替代办法) (中文(简体) ).
安装
npm 安装@ avallone- io/ rls
使用量
要创建 RLSConnection 实例, 您需要与 db 的原始连接 。 按常规设置打字机配置, 然后将其连接包成一个 RLSC 连接 例如,针对每项请求.
这将运行一个 set "rls.tenant_id" 财务报告和审定财务报表 set "rls.actor_id" 对于每个请求,并在查询执行后重新设置.
RLS 政策
您的数据库政策将 必须 使用 rls.tenant_id 财务报告和审定财务报表 rls.actor_id 为了实施隔离。 政策实例:
CREATE POLICY tenant_isolation ON public."category" for ALL
USING ("tenant_id" = current_setting('rls.tenant_id'))
with check ("tenant_id" = current_setting('rls.tenant_id'));
运通/韩国
例如,假设明示申请:
app.use((req, res, next) => {
const dataSource = await new DataSource({...}).initialize(); // create a datasource and initialize it
// get tenantId and actorId from somewhere (headers/token etc)
const rlsConnection = new RLSConnection(dataSource, {
actorId,
tenantId,
});
res.locals.connection = rlsConnection;
next();
});
// your handlers
const userRepo = res.locals.connection.getRepository(User);
await userRepo.find(); // will return only the results where the db rls policy applies
在上述例子中,您必须配合所提供的连接. 直接调用 TypeORM 函数将和没有意识到的原始数据源对象一起工作.
雀巢JS一体化
如果您正在使用 NestJS , 这个库会提供帮助, 帮助您了解您的连接和询问租户 .
创建您的 TypeORM 配置并使用 TypeORM 模块加载 .forRoot- 那你得装上 RLSModule 与 .forRoot 在那里你将定义 在哪里拿 tenantId 财务报告和审定财务报表 actorId 从. 第二部分是,你现在需要替换 TypeOrmModule.forFeature 与 RLSModule.forFeature这应该是1比1的替换.
您可以输入非实体依赖模块和提供者。 第一个数组导入模块,第二个数组注入提供者.
使用时 RLSModule.forRoot 它会设置你的 scope 改为 REQUEST确定您理解这个计划的意义, 特别是阅读关于请求范围验证策略的内容 雀巢文件。 。 。 .
这个 RLSModule.forRoot 接受工厂的乐趣作为合成或非合成功能.
app.controller.ts
@Module({
imports: [
TypeOrmModule.forRoot(...),
RLSModule.forRoot([/*Module*/], [/*Service*/], async (req: Request, /*serviceInstance*/) => {
// You can take the tenantId and actorId from headers/tokens etc
const tenantId = req.headers['tenant_id'];
const actorId = req.headers['actor_id'];
return {
actorId,
tenantId,
};
}),
RLSModule.forFeature([Post, Category]) // <- this
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
现在您可以使用正常的模块注入,用于寄存器,服务等.
要在服务中注入 RLS 连接, 您可以使用 @Inject(TENANT_CONNECTION) 地点 TENANT_CONNECTION 从 @avallone-io/rls。 。 。 .
export class AppService {
constructor(
@InjectRepository(Category)
private categoryRepo: Repository<Category>,
@Inject(TENANT_CONNECTION)
private connection: RLSConnection,
) {}
// you can now use categoryRepo as normal but it will
// be scoped for RLS. Same with the connection.
}
相同,不直接使用来自 dataSource 因为它会给你与数据库的默认连接,而不是被包裹的实例.
详情请查看 test/nestjs/src。 。 。 .
类型器 >v0.3.0
自打字机v0.3.0起,连接类被"数据源"所取代. 这个模块仍然使用连接作为其语言,现在也有助于区分实际数据库连接(typeorm Data Source)和RLS slapper(RLSConnection). 但是,如果想与打字机绝地游戏等同,则有别名用于 RLSConnection 调用 RLSDataSource。 。 。 .