存储用户权限的最佳方式?
Posted
技术标签:
【中文标题】存储用户权限的最佳方式?【英文标题】:Best way to store user permissions? 【发布时间】:2011-04-10 01:57:05 【问题描述】:设计一个相当复杂的网站,在一个页面上运行大量 ajax。我已经到了一些用户需要有特定权限才能做事而一些用户需要停止操作的地步。我已经在我的数据库中设置了用户角色并且一切正常,但我想知道是否有一种更简单/更安全的方法来存储每个权限。
目前,当用户登录时,他们的特定权限会从数据库中获取并加载到会话数组中。要检查用户是否有权限,我只需检查权限是否包含在数组中。这看起来很慢,几乎就像我错过了一个更好的解决方案。
此外,会话显然可以由用户编辑...有更安全的方法吗?
我曾考虑为每个检查运行一个查询,但这可能会大大增加简单 ajax 请求的加载时间。
我对任何想法持开放态度。谢谢。
【问题讨论】:
【参考方案1】:首先,用户不能编辑会话变量。唯一保存在用户机器上的是会话 ID。然后服务器使用该 ID 来获取仅存储在服务器上的键/值对。从客户的角度来看,不可能随心所欲地改变价值观。
其次,我不会太担心数据库连接。避免重复自己,但不要太担心第一次连接。
最后,我最喜欢在不创建角色的情况下获得多个权限的方法是使用二进制数学。有些人喜欢,有些人不喜欢,但我觉得它很有用。
要使用这种方法,我们定义以下值进行成像:
CAN_EDIT_SOMETHING = 1 // Powers of 2
CAN_SEE_SOMETHING_ELSE = 2
CAN_DO_ADMIN_STUFF = 4
... = 8
要赋予人们多个权限,请使用二进制 OR
PERMISSIONS = CAN_EDIT_SOMETHING | CAN_DO_ADMIN_STUFF
为了说明这是如何工作的,我们可以看看这些位:
0b0001
OR 0b0100
---------
0b0101
要检查某人是否有权限,请使用二进制 AND
if( PERMISSIONS & CAN_EDIT_SOMETHING != 0 )
要了解它是如何工作的,我们再次查看这些位
0b0101
AND 0b0001
----------
0b0001 // Not equal to 0. They must have that permission!
此方法的最后一个好处是它允许您轻松地将多个权限组合成“元权限”
// If both EDIT_SOMETHING and ADMIN_STUFF are tasks that an admin
// can perform, we can combine them easily
//
IS_FULL_ADMIN = CAN_EDIT_SOMETHING | CAN_DO_ADMIN_STUFF
// We can then use this value exactly as we do any other permission
//
PERMISSIONS = IS_FULL_ADMIN | CAN_SEE_SOMETHING ELSE
如果你愿意,可以使用它,但它是你的武器库中的一个很好的技巧。
【讨论】:
感谢您解释二进制文件,我想在第一次设计角色时使用类似的东西。我最终使用了 2 个包含用户角色和 indv 权限的 db 表,这对我来说更有意义。我也可以发誓我在某个地方看到可以提取您的会话数据并对其进行编辑,尽管很困难。也许不是。 @Capt Otis,就像我说的那样,它在某些情况下有效,而在其他情况下无效。你比我更了解你的系统。至于会话,这就是它在 php 中的工作方式,但您应该检查您正在使用的系统。使用 Fiddler 或 Wireshark 检查流量并查看用户实际看到的内容。如果来回传递的只是一个 ID(当值改变时它不会改变),那么你很好。如果您注意到比 ID 更多的值,或者如果您注意到会话值更改时会话信息发生更改,那么您就有麻烦了,您最好仔细查看您的会话 :)【参考方案2】:我觉得还可以!你可以看看一些软件来提高你的会话速度。
每次查询数据库并不像听起来那么糟糕!首先,您可能无论如何都需要连接到数据库,其次,如果您在登录时查询用户权限,那么所有相关行都可能位于缓冲区中并且不需要 IO,第三,查询单个权限单个用户将比查询一个用户的所有权限要轻得多。
【讨论】:
【参考方案3】:您对模型的解释似乎有些混乱。许可是主体授权和客体授权的产物。你真的为每个主题和对象的组合存储这些产品吗?这是一个非常低效且难以管理的解决方案。
此外,用户显然可以编辑会话
WTF?????!!!!
会话数据只能由您在代码中定义的方法更改 - 如果用户能够以他们喜欢的任何方式修改会话数据的任何部分,那么这是您需要解决的第一个问题 - 直到您这样做,几乎不可能依赖您的身份验证/授权方法的任何部分,除非您将身份验证完全移出应用程序代码的域(顺便说一句:这不是解决问题的正确方法)。
当然,搜索一个非常大的数组(不确定实际的断点 - 但在 n=1000 的区域内 - 但有很多变量会影响这一点)可能比从数据库中获取结果要慢得多。
如果不了解当前系统的工作原理,就很难说出自己做错了什么。是one of these吗?
【讨论】:
以上是关于存储用户权限的最佳方式?的主要内容,如果未能解决你的问题,请参考以下文章