我正在尝试实现行级安全性,以便我们的应用程序可以实施更严格的访问控制。
我们正在研究的技术之一是Oracle的虚拟专用数据库,它通过基本上使用where
子句谓词来扩充针对特定表的所有查询,从而允许行级安全性。由于我们处于Web环境中,因此我们需要在单个请求的线程内部在Oracle中设置特殊上下文。我们将连接池与服务帐户一起使用。
我开始研究Eclipse Link和Hibernate。 Eclipse Link似乎有events完全适合这个模型。
这将涉及我们从hibernate迁移,这不是问题,但我们将为这些事件绑定到EL。
Oracle似乎暗示它们是在Web Logic product中的数据源级别实现的。
上下文由WebLogic数据源代码设置和清除。
问题:使用一系列事件在DataSource级别执行此操作更合适。我应该最关注的事件或方法是什么?
已添加问题:如何扩展连接池以使用某些自定义数据安全地初始化oracle上下文?我在Apache中挖掘,似乎扩展BasicDataSource并不能让我访问任何允许我在Spring完成时清理连接的东西。
我需要建立连接,并在退出/进入连接池时清理连接。我希望实现这么简单,没有人可以通过打破产品的微妙平衡来搞砸它。
- Specifically we are currently using Apache Commons DBCP Basic Data Source
这将允许我们使用各种方式连接到数据库,并仍然强制执行我们的安全性。但我没有看到一个很好的例子或一组事件可以使用,滚动我自己的安全生命周期从来都不是一个好主意。
答案 0 :(得分:2)
我最终通过扩展一些Apache组件来解决我的问题。
首先,我延长了org.apache.commons.pool.impl.GenericObjectPool
并覆盖了borrowObject()
和returnObject()
。我知道池中对象的类型(java.sql.Connection
),所以我可以安全地投射和使用它们。
因为在我的情况下我使用的是Oracle VPD,所以我能够在Application上下文中设置信息。我建议你更深入地阅读这些内容。它有点复杂,有很多不同的选项可以在不同的上下文级别和RAC节点之间隐藏或共享数据。 Start
本质上我所做的是生成一个nonce并使用它来实例化oracle中的会话,然后将用户的访问级别设置为该会话中的变量,然后Oracle VPD策略将读取并用于执行行级过滤。
我在被覆盖的borrowObject()
和returnObject()
中实例化并销毁了这些信息。我运行的SQL是这样的:
CallableStatement callStat =
conn.prepareCall("{call namespace.cust_ctx_pkg.set_session_id(" + Math.random() + ")}");
callStat.execute();
注意math.random()
isn't a good nonce.
接下来只是扩展org.apache.commons.dbcp.BasicDataSource
并通过覆盖createConnectionPool()
来设置我的对象池。请注意,我这样做的方式禁用了一些我不需要的功能,因此您可能需要比我更多或更少重写。
答案 1 :(得分:0)
为了简单起见,您可以尝试任何对象级安全机制,例如Spring Security ACL。
答案 2 :(得分:-1)
您需要在应用程序层执行此操作。你需要一个预提交钩子和一个后读钩子。
预提交挂钩用于确保来自客户端的数据由授权修改该数据的用户呈现。这可以防止未经授权的用户覆盖他们无法访问的数据。
它不直观,但是后读取挂钩用于防止客户端访问不允许用户查看的数据。这发生在后视图中,因为这是在应用程序层而不是在数据层强制执行的。应用程序无法知道在从数据层检索数据之前是否允许调用者访问数据。在post read hook中,您将根据登录用户的凭据评估返回的每行上的凭据,以确定是否允许访问。如果在任何行上拒绝访问,则会引发异常,并且不会将数据返回给客户端。
以这种方式完成的应用程序级安全性要求您有办法将表中的每一行连接到访问它所需的权限/角色,以及在运行时评估用户在服务器上的权限的方法。
希望有所帮助。
答案 3 :(得分:-2)
通过使用其他Commons DBCP数据源,您将获得更好的控制。 基本的就是:基本:) org.apache.commons.dbcp.datasources包中的那些为您提供了更细粒度的控制。