我目前正在尝试使用Symfony(2.3版(创建自己的授权系统。我不确定我是否把事情复杂化了,我对Symfony和SOA很陌生。我正在创建自己的授权系统,因为我需要根据当前用户、其角色和当前客户(当前用户可以更改客户(及其产品来限制权限。
我目前拥有的,我认为可能太复杂了,如下:
对于每个实体,我有一个仅用于读取操作的存储库:
MyBundle/Entities/
Customer.php/CustomerRepository.php
Product.php/ProductRepository.php
...
抽象存储库的使用以及创建/更新/删除的处理。我有一个使用存储库的每个实体的管理器类(代理存储库和使用不同存储库的组合(。
MyBundle/Manager/
CustomerManager.php
ProductManager.php
...
然后我有我的类,这些课程根据当前用户,其角色和当前选定的客户及其产品获得授权。他们使用管理器来加载所有 ACL 数据。
MyBundle/Authorization/
AuthCustomers.php //Allowed customers to which user is assigned
AuthRights.php //Rights according to user and customer
服务如下所示:
auth.manager.product:
class: MyBundle'Manager'ProductManager
arguments: ["@doctrine.odm.mongodb.document_manager"]
auth.manager.customer:
class: MyBundle'Manager'CustomerManager
arguments: ["@doctrine.odm.mongodb.document_manager"]
auth.authorization.authorization_rights_factory:
class: MyBundle'Authorization'AuthorizationRightsFactory
arguments: ["@auth.manager.role", "@auth.manager.customer"]
auth.authorization.authorization_customers_factory:
class: MyBundle'Authorization'AuthorizationCustomersFactory
arguments: ["@auth.manager.group", "@auth.manager.customer"]
到目前为止,我实际上认为这是可以的。但是我现在需要的和我担心的是,当对这些实体中的任何一个执行某些操作时,如果允许我这样做,我实际上需要检查我的AuthorizationXXX
服务。因此,Authorization
类依赖于Manager
,反之亦然。
为了抽象它(为了防止无限引用,我可以在控制器和命令脚本中重用它(,我现在将创建另一个服务,在其中注入Authorization
和Manager
服务并执行这些检查。所以我实际上会有另一位经理来服务我。
最后,我将拥有 7 个实体,具有 7 个存储库和 7 个管理器 + 一些授权类 + 7 个服务来组合管理器和授权类。
现在的问题是,这是正确的方法吗?我真的觉得我把事情复杂化了。欢迎任何更简单的建议:)
选民似乎符合您的需求,请查看文档:http://symfony.com/doc/current/components/security/authorization.html#voters
您可以创建一个 Voter,它将当前用户、他的角色和当前客户作为参数,如果您的业务规则得到遵守,则返回 true,如果不符合,则返回 false。
我现在只保留了结构,只是稍微改变了层的含义。我现在拥有并感到舒服的是:
对于只读操作Repositories
,知道其他存储库(在这里,我一开始就过头了,希望让存储库彼此不知道(。
Manager
处理实体的持久性并代理到Repositories
的读取操作。他们不在乎Authorization
.
Authorization
只处理我的授权事务的服务,因此它们可以在任何地方重用,而无需执行Symfony特定的事情。
Model
服务结合了Manager
和Authorization
以及一般的所有部门。实际上,Symfony控制器只会调用模型服务的方法。但是有了这个,我也可以将其重用于命令行脚本等。
我仍然有很多课程,但他们现在分开得很好,只做他们的东西,可以很容易地更换。
总的来说,我还详细查看了FOSUserBundle以获得一些灵感。我认为他们总体上解决得很好。