JOOQ 中的行级安全实施

问题描述 投票:0回答:1

我想使用 JOOQ 库在 Java 中实现 Oracle 行级安全性功能

这里是JOOQ查询代码示例:

Result<Record> result = dslContext.select().from(Employee.EMPLOYEE).fetch();

上面的代码将生成如下 SQL:

select [dbo].[Employee].Id,... from [dbo].[Employee]

我想添加一个 where 子句来过滤特定于用户安全的数据,如下所示:

select [dbo].[Employee].Id,... from [dbo].[Employee] WHERE [dbo].[Employee].Security IN (1,2)
java sql jooq
1个回答
2
投票

显式谓词

除非我错过了一些很好的 SQL Server 功能,其中行/记录包含一个名为

.Security
的伪列来实现行级安全性,否则您应该能够简单地编写

dslContext.select()
          .from(EMPLOYEE)
          .where(EMPLOYEE.SECURITY.in(1, 2))
          .fetch();

有关 jOOQ 谓词构建的更多信息,请参阅此处的手册:

特别是

IN
谓词:

使用政策

jOOQ 3.19 引入了对#2682的政策支持,另请参阅:

通过策略,您可以简单地在您的

Configuration
上指定类似的内容:

Configuration configuration = ...;
configuration.set(new DefaultPolicyProvider()
    .append(
        EMPLOYEE,
        EMPLOYEE.SECURITY.in(1, 2))
);

现在,所有查询(包括 DML)都将阻止访问谓词不成立的数据

TRUE

使用jOOQ的ExecuteListener的通用解决方案

根据您的评论,您正在寻找一种通用方法来使用附加谓词修补所有 SQL 语句,无论特定程序员输入什么。

您可以使用 jOOQ 做到这一点,但请注意,如果程序员绕过 jOOQ,这只会帮助您强制执行谓词,而不是保证它。您可以做的是设置一个

ExecuteListener
,拦截
renderStart()
事件,以便修补/替换正在执行的查询。沿着这些思路:

@Override
public void renderStart(ExecuteContext ctx) {
    if (ctx.query() instanceof Select) {

        // Operate on jOOQ's internal query model
        SelectQuery<?> select = null;

        // Check if the query was constructed using the "model" API
        if (ctx.query() instanceof SelectQuery) {
            select = (SelectQuery<?>) ctx.query();
        }

        // Check if the query was constructed using the DSL API
        else if (ctx.query() instanceof SelectFinalStep) {
            select = ((SelectFinalStep<?>) ctx.query()).getQuery();
        }

        if (select != null) {
            // Use a more appropriate predicate expression
            // to form more generic predicates which work on all tables
            select.addConditions(EMPLOYEE.SECURITY.in(1, 2));
        }
    }
}

当然,上述内容还有改进的空间。欢迎在用户组

讨论用例

使用jOOQ的VisitListener的通用解决方案

如果您愿意深入了解 jOOQ 的内部结构,您还可以尝试实现

VisitListener
并实际转换 jOOQ 的查询的 AST 表示形式。这记录在这里:

使用视图的通用解决方案

虽然上述方法有效,但我个人建议您为此使用视图并向开发人员隐藏实际的表。示例:

CREATE VIEW v_employee AS
SELECT a, b, c, ... 
FROM t_employee
WHERE t_employee.security in (1, 2)

通过适当的拨款,您可以向开发人员隐藏表,确保他们只会使用始终具有所需谓词的视图

© www.soinside.com 2019 - 2024. All rights reserved.