如何在Hibernate中限制数据库级别的用户访问

时间:2009-02-18 01:25:31

标签: hibernate jboss db2 data-access

应用

我需要实现一个将由不同用户使用的Web应用程序。每个用户对各种表具有不同的权限,例如

  • 用户A可以在表Student
  • 中查看字段'name'和'address'
  • 用户B可以查看字段“名称”和“电话号码”,但不能查看表格中的“地址”Student
  • 用户C可以查看和修改上述所有字段

  • 我将在UI级别有一些限制某些访问的内容,例如:为没有修改条目权限的用户隐藏“编辑”按钮。但是,我认为我应该在较低级别(在数据库级别可能?)有一些东西,以确保数据安全。


    问题

    我正在为我的应用程序使用Hibernate,JBoss,DB2和Struts。我想我应该使用某种类型的JBoss LoginModule,它使用用户/密码/角色对数据库进行身份验证(但我可能错了(?))。我做了一些研究,并提出了以下选项,但似乎没有一个适合我的情况。我认为这是多用户Web应用程序中非常常见的数据访问问题。有人可以指点我正确的方向吗? 提前谢谢!

    1. hibernate.cfg.xml中的'grant'标记与JACC事件侦听器一起使用。这可以在所有休眠实体上设置“插入”“更新”“读取”权限。但是,如果我需要更精细的控件怎么办?我需要在某些字段而不是整个对象上设置权限。 http://www.hibernate.org/hib_docs/v3/reference/en-US/html/objectstate-decl-security.html

    2. 限制每个ejb的getter / setter方法的权限。如果我理解正确,这需要为每个用户配置文件手动配置每个bean,这对我来说似乎不切实际。 EJB Method Permissions

    3. 对DAO进行编码以检查用户权限。滚动我自己的实用程序函数,每次调用特定的DAO方法时都会检查巨型权限表,以确定登录用户是否可以执行操作。

    4. 在Hibernate中使用'interceptor'和'events'。为每个类定义特定的“onLoad”,“onSaveorUpdate”等事件和拦截器。在这种情况下,我可以为各个字段指定权限级别吗? http://www.hibernate.org/hib_docs/v3/reference/en-US/html/objectstate-events.html

    5. 我可能会在错误的树上吠叫。所有上述内容似乎都是劳动密集型而且不是很聪明。上述选项都没有为我提供在运行时更改用户权限的编程方法,这在管理员级别用户希望在此应用程序中为其他用户提供更多控制权时非常有用。


      在这里进行数据访问控制的好方法是什么?

    3 个答案:

    答案 0 :(得分:3)

    1. 向您的实体添加安全密钥,为权限创建表,并使用entitytype以及带角色的安全密钥链接用户。通过这种方式,您可以这样说:Admin_role可以访问Student(Entitiy类型)并执行读取(Permission中的操作)和Write(Operation),而Student_role可以访问Student_key用于他/她自己和Read_permission。您可以通过将地址重构为实体并向其添加安全密钥来修复地址。

      1. 你的四号可能有一个封闭世界的假设,并说除非你可以为用户的当前角色,将属性名称与字典中的标志(实体+属性)-hash链接到标志,封闭的世界假设是默认情况下不允许读取。当然,你没有获得任何写权限等。

      2. 您可以在数据库中定义视图,并使用数据库身份验证系统为其分配权限。如果您能够自己编码,这可能是最干净的方式,根据我们的角色选择调用哪个视图的方式。 (我以前的RDBMS老师会喜欢我说这个;))这也离Hibernate有点偏离,并将你的东西更多地耦合到数据库。这取决于您的代码需要移动/可移植的程度,我想。

      3. 使用您的通用dao(IRepository)周围的方面,它根据您的权限重写查询;这意味着您在代码中拥有基于权限的安全性。

    2. 隐藏在gui中的编辑按钮实际上只有在你第一次将权限移植到代码时才能完成,就像在我的观点1中一样。我建议你看一下Ayendes blog的开源实现这是他非常熟练的编码员。

    答案 1 :(得分:2)

    另一种选择可能是使用自定义类型。例如,不是将char映射到String,而是将其映射到自定义类型,如SecureString。在映射中给它一个带有某种唯一标识符的参数,例如: TABLE.COLUMN。然后在自定义类型的nullSafeGet方法中,您可以调用安全服务以查看是否填充该值或仅将其设置为null。您可能还必须使用ThreadLocal来存储标识用户或角色的内容。你只需要创建一些自定义类型来包装字符串,双精度,日期,整数等。我已经做了类似的事情,允许将日期转换为用户的时区。

    答案 2 :(得分:1)

    我喜欢Henrik's建议使用观点。

    Hibernate filters可能会有效,但我认为这些更适合过滤行而不是列。

    <德尔> 您还可以使用[基于地图的动态模型](http://www.hibernate.org/hib_docs/reference/en/html/persistent-classes-dynamicmodels.html)以及单独的[命名查询](http:// www.hibernate.org/hib_docs/reference/en/html/querysql-namedqueries.html),而不是部分填充的bean。那么你的视图代码只会检查Map是否包含`address`的条目,如果找到则显示该字段?
    相关问题