构建更好的访问控制系统
我正在构建一个访问控制系统,作为我正在开发的网络框架的一部分。我想让它变得超级灵活和很棒。您能为我的设计提供意见和见解来帮助我吗?这是我到目前为止的工作(我的具体问题在底部):
用户
- 用户有一个用户名(32 个字符,无空格)和密码
- 用户有一个或多个必须验证的电子邮件地址
- 用户可以使用他们的用户名或任何电子邮件地址登录
- 用户可以关联到零个或多个帐户
帐户
- 帐户代表一个或多个用户
- 每个用户可能对帐户具有特定的权限或角色(例如,帐户所有者或“可以添加新用户”)
- 所有帐户都与帐户类型绑定
帐户类型
- 帐户类型具有零个或多个帐户类型角色
- 帐户类型具有零个或多个帐户类型功能
帐户类型角色
- 例如,“所有者”、“管理员”、“高级用户”、“访客”等。
- 帐户类型角色是帐户类型权限的集合
帐户类型权限
- 帐户类型权限是系统中应用程序逻辑将验证的特定操作。
- 它们可能引用父级,因此可以对它们进行分层分组,
- 例如:
- “用户管理”
- “添加用户”
- “删除用户”
- “用户管理”
- 这些权限可能专门针对帐户类型功能
帐户类型功能
- 可以在帐户上激活帐户类型功能以授予其更多权限
- ,例如“标准”帐户”或“高级帐户”
- 如果在帐户上激活这些功能,帐户所有者将获得对系统的更大访问权限。
- 它们在激活或停用时会被跟踪,并且可以定期或按需计费
问题
根据用户操作检查应用程序逻辑的最佳方法是什么?我正在考虑将用户的所有权限存储在其会话的对象中(这将需要注销/登录来刷新权限,我不喜欢这一点 - 关于实时权限管理的任何想法吗?):
{
"All Permissions": {
"User Management": {
"Add User",
"Delete User"
},
"Premium Account": {
"Download Files",
"Upload Files"
},
}
}
然后我会声明系统中特定操作所需的权限。也许是这样的:
Permission::require('Add User');
如果声明的权限不在用户权限对象中,则请求将失败。不过,这对于每个用户操作来说似乎都很激烈。另外,如果权限的另一个子集具有字符串“添加用户”怎么办?
预先感谢您对此的任何帮助!
I'm in the process of a building an access control system as part of a web framework I am developing. I want to make it super flexible and awesome. Can you help me by providing input and insight on my design? Here is my work so far (my specific questions are at the bottom):
Users
- Users have a username (32 characters, no spaces) and password
- Users have one or more e-mail addresses that must be verified
- Users may login using either their username or any of their e-mail addresses
- Users may be associated to zero or many accounts
Accounts
- Accounts represent one or more users
- Each user may have specific permissions or roles for an account (e.g., account owner or "can add new user")
- All accounts are tied to an account type
Account Types
- Account types have zero or many account type roles
- Account types have zero or many account type features
Account Type Roles
- E.g., "Owner", "Administrator", "Power User", "Guest", etc.
- Account type roles are a collection of account type permissions
Account Type Permissions
- Account type permissions are specific actions in the system that application logic will verify against
- They may reference a parent, so they can be hierarchically grouped
- E.g.:
- "User Management"
- "Add User"
- "Remove User"
- "User Management"
- These permissions may be specifically for an account type feature
Account Type Features
- Account type features may be activated on an account to give it more permissions
- E.g., "Standard Account" or "Premium Account"
- These features, if activated on an account, will give the account owner greater access to the system
- They are tracked when they are activated or deactivated and can be billed against periodically or on demand
Questions
What is the best way to have application logic check against a user action? I was thinking of storing all of a user's permissions in an object for their session (which would require a logout/login to refresh permissions, which I am not a fan of - any ideas on real time permission management?):
{
"All Permissions": {
"User Management": {
"Add User",
"Delete User"
},
"Premium Account": {
"Download Files",
"Upload Files"
},
}
}
I would then declare permissions that are required for a specific action in the system. Maybe something like:
Permission::require('Add User');
If the declared permissions were not in the users permission object, the request would fail. This seems kind of intense for each user action though. Also, what if another subset of permissions has the string "Add User"?
Thanks in advance for any help with this!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
查看您的帐户类型权限,您似乎考虑了访问控制列表 (ACL) 样式的系统设计。
如果您想让它变得超级灵活和出色,那么我建议这不是一个好的设计。 ACL 系统适用于简单的权限 - 也许在您的场景中这实际上是可以的 - 但一旦授予权限的规则变得哪怕是一点点动态 - 也就是说,依赖于用户身份或角色之外的任何上下文数据 - ACL 就会失效平快。
该视频详细介绍了 ACL 的缺陷,并讨论了实现访问控制的替代方法,该方法考虑了实际情况世界局势。
而且,这之前已经完成了(尽管令人惊讶的是我们可以查看的实现很少);也许看看 Rhino Security< /a>.原始链接 http://ayende.com/Blog/category/548.aspx 是损坏,因此保留互联网存档链接以供参考。
Looking at your Account Type Permissions, it appears you have an Access Control List (ACL) style system design in mind.
If you want to make it super flexible and awesome, then I'd suggest this is not a good design. ACL system's work for simple permissions - and maybe that actually is ok in your scenario - but as soon as the rules for granting permission become even the slightest bit dynamic - that is, relying on any contextual data beyond the user's identity or roles - ACL's fall flat fast.
This video goes into some detail about the failings of ACL's and discusses alternate ways to implement access control that accounts for real-world situations.
Also, this has been done before (though there's surprisingly little out there for implementations we can look at); perhaps have a look at Rhino Security. Original link http://ayende.com/Blog/category/548.aspx is broken, so keeping internet archive link for reference.
我发现我喜欢的一种方式是一种“级联”权限。您拥有一组核心权限 - 比如说读、写、删除 - 并且这些权限可以分配给组或用户。
或者,您可以指定“组”而不是用户名。
然后您可以简单地使用表中的值来排序和查找记录。这允许灵活地成为具有互斥权限等的多个组的成员。
One way I've seen that I like is a sort of "cascading" permissions. You have a core set of permissions - let's say read, write, delete - and those can be assigned to a group or a user.
Alternatively you can specify a "group" instead of a username.
And then you can simply use the values in the table to sort and look for records. This allows for the flexibility of being a member of multiple groups with mutually exclusive permissions, etc.
我会看一下Java系统的权限:
http://download.oracle.com/javase/6/docs/api/java/security/Permission.html
它使用“蕴含逻辑”;也就是说,权限对象决定是否允许给定的操作(即权限是否“暗示”对资源的访问)。我还会查看 BasicPermission,因为它有一个非常简单的权限命名空间规范。在您的示例中,它将是(遵循 CRUD 命名法)
在我们的 web 应用程序中,我们为每个可以请求的资源或过程分配一个权限,并为每个用户分配一组权限。然后我们执行
boolean isAuthorized = user.permissions.implies(requestedResource.permission); (隐含标准封装)
以确定是否允许用户访问。
I would take a look at the Java system for permissions:
http://download.oracle.com/javase/6/docs/api/java/security/Permission.html
It uses "implication logic"; that is, the permission object is what decides whether the given action is allowed (i.e. whether the permissions "implies" access to a resource). I would also check out the BasicPermission as it has a pretty straight-forward namespace spec for permissions. In your example it would be (following the CRUD nomenclature)
In our webapp, we assign a permission to each resource or procedure that can be requested, and a set of permissions to each user. We then do a
boolean isAuthorized = user.permissions.implies(requestedResource.permission); (standard encapsulation implied)
to determine if the user is allowed access.
这是我的两种感觉,它的价值。
首先,我想说,当您开始设计这个时,请考虑 OOP 以及它将如何应用于系统内的实体。用户、User_Role、角色、Role_Permissions、帐户、Account_Types、Account_Type_Features 等。
用户:
- 应该允许使用 OpenID,因为它正在获得关注
- 在 ID 或 UUID 之间进行选择以实现数据库可移植性的选项
用户角色:(不是帐户类型角色)我鼓励您在这里非常具体。例如,高级用户和管理员之间的界限在哪里?
管理员和所有者有什么区别?只要这些被明确定义(而不是模糊),那么它就会起作用。
如果您的用户群中有任何问题,很快您就会拥有一组复杂的角色和权限。
我会将其保持在最低限度以保持清洁。用户将弄清楚如何使用他们所得到的东西进行工作。
另外,我会将其更改为用户类型角色。角色应适用于用户,而不是帐户。
角色权限:(不是帐户类型权限)
应将其更改为角色权限。权限扩展到用户角色,而不是帐户或用户。
根据我的经验,设计越清晰,后续出现混乱的空间就越小。
另外,像躲避瘟疫一样避开 ACL。使其成为简单的一对一关系。我还没有找到实施 ACL 的理由
适用于任何基于网络的系统。其他基于权限的系统更容易理解、维护和使用。没有任何意义
让事情变得复杂化。
帐户类型特征:
请注意不要掩盖帐户类型权限和帐户类型功能。您的第一个要点使用“权限”一词。
将其更改为功能。帐户类型将激活更多高级/高级功能(不是权限)。
权限管理:
对于在网络上运行的无状态应用程序,会话是最佳选择。优点是无需不断往返数据库
检查用户是否被授权。
不过,
Permission::require()
应遵循与会话相同的参数定义。这将防止其他权限子集的重叠。因此,调用类似于 Permission::require('User Management', 'Add User');
这意味着它将查找
$_SESSION['All Permissions']['User Management']['Add User']
这将防止歧义。
请记住简单更好。
Here is my two sense, for what it worth.
First I would say, when you start the design of this, think of OOP and how it would apply to entities within the system. Users, User_Role, Roles, Role_Permissions, Accounts, Account_Types, Account_Type_Features, etc.
USERS:
- Should be allowed to use OpenID as it is gaining traction
- The option to select between an ID or UUID for database portability
USER ROLES: (not ACCOUNT TYPE ROLES) I would encourage you to be very specific here. For example, where do you draw the line between power user and administrator?
What's the difference between ADMIN and OWNER? As long as these are clearly defined (and not blurry), then it will work.
If there is any question amongst your user base, pretty soon you will have a convoluted set of roles and permissions.
I would keep this to a minimum to keep things clean. Users will figure out how to work with what they are given.
In addition, I would change this to USER TYPE ROLES. The roles should apply to the user, not the account.
ROLE PERMISSIONS: (not ACCOUNT TYPE PERMISSIONS)
This should be changed to ROLE PERMISSIONS. The permissions are extended to a users role, not an account or a user.
In my experience the more clear the design, the less room for confusion down the road.
Also, avoid ACL like the plague. Make it a simple one-to-one relationship. I have yet to find a reason to implement ACL
for any web based system. Other permission based systems are much easier to understand, maintain, and use. There is no sense
in complicating the matter.
ACCOUNT TYPE FEATURES:
Be careful not to obscure the Account Type Permissions and Account Type Features. Your first bullet point uses the word permissions.
Change it to features. The account type will activate more advanced / premium features (not permissions).
Permission Management:
For a stateless application running on the web, sessions are the way to go. The advantage is no roundtrips to the DB to constantly
check if a user is authorized.
Permission::require()
should follow the same parameter definitions as the Sessions though. This will prevent overlap of other subset of permissions.So the call would be something like
Permission::require('User Management', 'Add User');
This means it would look for
$_SESSION['All Permissions']['User Management']['Add User']
This will prevent ambiguity.
Remember SIMPLE is BETTER.
Zed Shaw 关于 ACL 及其局限性有一些有趣的说法。在你继续沿着这条路走下去之前,绝对值得一看。
http://vimeo.com/2723800
Zed Shaw had some interesting things to say about ACL's and their limitations. Definitely worth watching before you go any further down this route.
http://vimeo.com/2723800
我建议您研究一下 Zend Framework 中的 Zend_Acl。与大多数 Zend 软件包一样,它有一个陡峭的学习曲线。但是,当您完全掌握资源、操作、角色关系时,它就会成为您自己的 ACL 实施的非常通用且强大的基础。
对现有 ACL 包和模式进行一些研究。
I advise you to look into the Zend_Acl from Zend Framework. Like most Zend packages it has a steep learning curve. But when you fully grasp the resource, action, role relationship it becomes a verry versatile and powerfull foundation for your own ACL implementations.
Do some research into existing ACL packages and patterns.
我没有任何具体的建议,但我熟悉的两个具有非常好的灵活访问/权限系统的系统是 Drupal 和 Plone。你可能会做比复制它们中任何一个的工作方式更糟糕的事情。他们经过多年的实际测试。
I don't have any specific advice but two systems I'm familiar with that have very good flexible access/permission systems are Drupal and Plone. You could do far worse than copying how either of them work. They've had years of real-world testing behind them.
您使用的语义有点令人困惑。例如,“所有者”、“管理员”、“高级用户”、“访客”的帐户类型看起来更像“用户类型”。
另外,也许您可以将您称为“AccountPermissions”的东西作为 Account 的子类。这样,根据帐户类型,将应用不同的权限。
The semantics you are using are a bit confusing. For example Account Types of "Owner", "Administrator", "Power User", "Guest" seem more like "User Types".
Also, perhaps you could make the things you are calling "AccountPermissions" be a subclass of Account. This way depending on the type of the account, different permissions will apply.
看看这里
http://www.sqlrecipes.com/database_design/fine_grained_role_based_access_control_rbac_system-3/
概念基本上是相同的,并且使用起来很好,并且对于真正细粒度的访问控制来说速度相当快。
Have a look here
http://www.sqlrecipes.com/database_design/fine_grained_role_based_access_control_rbac_system-3/
The concepts are basically the same and its nice to use and considerably fast for really fine grained access control.