应用程序
我需要实现一个可供不同用户使用的网络应用程序。 每个用户对不同的表有不同的权限,例如
用户 A 可以看到表 Student
中的字段“姓名”和“地址”
用户 B 可以看到表 Student< 中的字段“姓名”和“电话号码”,但看不到“地址” /code>
用户C可以查看和修改上述所有字段
我将在用户界面级别设置一些内容来限制某些访问,例如,为无权修改条目的用户隐藏“编辑”按钮。 但是,我认为我应该在较低级别(也许在数据库级别?)有一些东西,以确保数据安全。
问题
我正在为我的应用程序使用 Hibernate、JBoss、DB2 和 Struts。 我想我应该使用某种 JBoss LoginModule,它使用用户/密码/角色对数据库进行用户身份验证(但我可能是错的(?))。 我做了一些研究并提出了以下选项,但似乎都不适合我的情况。 我认为这是多用户网络应用程序中非常常见的数据访问问题。 有人可以指出我正确的方向吗? 提前谢谢您!
-
将 hibernate.cfg.xml
中的“grant”标签与 JACC 事件侦听器一起使用。 这可以设置所有hibernate实体的“插入”“更新”“读取”权限。 但是,如果我需要更精细的控制怎么办? 我需要对某些字段而不是整个对象设置权限。 http://www.hibernate。 org/hib_docs/v3/reference/en-US/html/objectstate-decl-security.html
-
限制每个 ejb 的 getter/setter 方法的权限。 如果我理解正确的话,这需要为每个用户配置文件手动配置每个 bean,这对我来说似乎不现实。
EJB 方法权限
-
对 DAO 进行编码以检查用户权限。 滚动我自己的实用程序函数,每次调用特定的 DAO 方法时都会检查一个巨大的权限表,以确定登录用户是否可以执行该操作。
-
在 Hibernate 中使用“拦截器”和“事件”。 为每个类定义特定的“onLoad”、“onSaveorUpdate”等事件和拦截器。 在这种情况下,我可以指定各个字段的权限级别吗? http://www.hibernate.org/ hib_docs/v3/reference/en-US/html/objectstate-events.html
我可能对着错误的树吠叫。 以上这些看起来都是劳动密集型的,而且不是很智能化。 上述选项都没有为我提供在运行时更改用户权限的编程方法,当管理员级别用户想要在此应用程序中为其他用户提供更多控制权时,这将很有用。
在这里进行数据访问控制的好方法是什么?
The App
I need to implement a web app that will be used by different users. Each user has different privileges on various tables, e.g.
User A can see fields 'name' and 'address' from the table Student
User B can see fields 'name' and 'phone number', but not 'address' from the table Student
User C can see and modify all fields mentioned above
I will have something at the UI level to limit certain access, e.g. hide the "edit" button for users that don't have permission to modify entries. However, I think I should have something at a lower level (at a database level maybe?) just to ensure data security.
The Problem
I am using Hibernate, JBoss, DB2 and Struts for my app. I think I should use a JBoss LoginModule of some sort, which authenticates the user against a database with user/password/roles (but I may be wrong(?)). I have done some research and came up with the following options, but none seems to fit my case. I would think this is a very common data access problem in multi-user web apps. Could somebody please point me to the right direction? Thank you in advance!
-
Use the 'grant' tag in hibernate.cfg.xml
with JACC event listeners. This can set "insert" "update" "read" permissions on all hibernate entities. However, what if I need finer controls? I need to set permissions on certain fields instead of the entire object. http://www.hibernate.org/hib_docs/v3/reference/en-US/html/objectstate-decl-security.html
-
Limit permissions on getter/setter method of each ejb. If I understood this correctly, this requires manual configuration of every single bean for every user profile, which seems unrealistic for me.
EJB Method Permissions
-
Code the DAO's to check for user permissions. Roll my own utility function that checks a giant permission table everytime a particular DAO method is called to determine if the logged in user can perform the action or not.
-
Use 'interceptor' and 'events' in Hibernate. Define specific "onLoad", "onSaveorUpdate" etc. events and interceptors for each class. Can I specify permission level for individual fields in this case? http://www.hibernate.org/hib_docs/v3/reference/en-US/html/objectstate-events.html
I might be barking at the wrong tree. All of the above seem to be labour-intensive and not very intelligent. None of the above options give me programmatic ways to change user permissions at runtime, which would be useful when an admin-level user want to give another user more control in this app.
What is a good way of doing data-access control here?
发布评论
评论(3)
向您的实体添加安全密钥,创建权限表,并将用户与权限与实体类型以及安全密钥与角色链接起来。 这样你就可以这样说:Admin_role可以访问Student(实体类型)并执行读取(权限操作)和写入(操作),而Student_role可以访问他/她自己的Student_key和Read_permission。 您可以通过将其重构为实体并向其添加安全密钥来修复该地址。
您的第四个可能有一个封闭世界的假设,并表示除非您可以针对用户的当前角色,否则将属性名称与字典(实体+属性)中的标志链接到标志,封闭世界假设默认情况下不允许读取。 那么你当然不会获得任何写入权限等。
您可以在数据库中定义视图并使用数据库身份验证系统为其分配权限。 如果您能够自己编写代码,这可能是最干净的方法,即根据我们的角色选择要调用的视图的方法。 (我以前的 RDBMS 老师会喜欢我这么说的;))这也有点偏离 Hibernate,并将你的东西更多地耦合到数据库。 我想,这取决于您的代码需要的可移动性/可移植性。
在通用 dao (IRepository) 周围使用一个方面,它根据您的权限重写查询; 当然,这意味着您在代码中拥有基于权限的安全性。
隐藏在 GUI 中的编辑按钮实际上只有在您首先将权限移植到代码时才能完成,就像我的第 1 点一样。我建议您查看 Ayendes 博客 的开源实现,他是一位非常熟练的编码员。
Add a security key to your entities, create a table for permissions and link user with permission with entitytype and also with security key with role. This way you can say things like: Admin_role can access Student (Entitiy type) and do read (Operation in Permission) and Write (Operation) while Student_role can access Student_key for him-/herself and Read_permission. You can fix the address by refactoring that into an entity and adding a security key to it.
Your number four could have a closed-world assumption and say that unless you can for the current role of the user, link the property-name with a flag in a dictionary (entity+property)-hash to flag, the closed world-assumption being that reads are not allowed by default. Then of course you don't get any writes-permissions etc.
You can define views in your database and assign rights to them using the database authentication system. This is probably the most clean way if you are able to code yourself, the way of selecting which view to call depending on which role we are. (My former RDBMS-teacher would love me for saying this ;)) This also goes away a bit from Hibernate and couples your stuff more to the database. It depends on how movable/portable your code needs to be, I guess.
Use an aspect around your generic dao (IRepository) which rewrites the queries based on your permissions; this implies you have the permission-based security in code of course.
The edit-button hiding in the gui can really only be done if you first port the permissions to code, like in my point 1. I suggest you have a look at Ayendes blog for an open-source implementation of this, he's a very skilled coder.
另一种选择可能是使用自定义类型。 例如,不要将字符映射到字符串,而是将其映射到 SecureString 等自定义类型。 给它一个在映射中带有某种唯一标识符的参数,例如table.column。 然后,在自定义类型的 nullSafeGet 方法中,您可以调用安全服务来查看是填充该值还是仅将其设置为 null。 您可能还必须使用 ThreadLocal 来存储一些内容来识别用户或角色。 您只需要创建一些自定义类型来包装字符串、双精度、日期、整数等。我已经做了类似的事情,允许将日期转换为用户的时区。
Another option might be to use custom types. For example, instead of mapping a char to a String, map it to a custom type like SecureString. Give it a parameter with some kind of unique identifier in the mapping, e.g. table.column. Then in the custom type's nullSafeGet method, you can call out to a security service to see whether to populate the value or just set it to null. You'd proably also have to use a ThreadLocal to store something to identify the user or role. You'd only have to create a handful of custom types to wrap string, double, date, integer, etc. I've done something similar to allow dates to be converted to the user's time zone.
我喜欢 Henrik 的建议使用视图。
Hibernate 过滤器 可能有用,但我认为这些更适合过滤掉行而不是列。
You could also use [Map-based Dynamic Models](http://www.hibernate.org/hib_docs/reference/en/html/persistent-classes-dynamicmodels.html) along with separate [named queries](http://www.hibernate.org/hib_docs/reference/en/html/querysql-namedqueries.html), rather than having partially filled beans. Then your view code would simply check if the Map contained a entry for `address`, and show the field if found?
I like Henrik's suggestion of using views.
Hibernate filters might work, but I think these are more for filtering out rows rather than columns.
You could also use [Map-based Dynamic Models](http://www.hibernate.org/hib_docs/reference/en/html/persistent-classes-dynamicmodels.html) along with separate [named queries](http://www.hibernate.org/hib_docs/reference/en/html/querysql-namedqueries.html), rather than having partially filled beans. Then your view code would simply check if the Map contained a entry for `address`, and show the field if found?