JOOQ中的行级安全性实现

时间:2013-06-26 15:39:44

标签: java sql jooq

我想使用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)

1 个答案:

答案 0 :(得分:1)

显式谓词

除非我遗漏了一些不错的SQL Server功能,其中行/记录包含一个名为.Security的伪列来实现行级安全性,否则您应该能够简单地编写

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

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

特别是IN谓词:

使用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));
        }
    }
}

当然,上述方面还有改进的余地。您可以在user group

上讨论用例

使用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)

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