Symfony UserProvider。我可以/我应该根据URL参数确定角色吗?

时间:2013-10-29 16:16:48

标签: symfony

我正在构建我的多租户Symfony应用程序的下一个版本。

让我们说我的租户是公司。每家公司都有我的应用程序域的子域。

例如,company1.example.com,company2.example.com。

Apache配置了ServerAlias * .example.com

我编写了一个UserProvider,以便用户通过公司和电子邮件地址是唯一的。同样的电子邮件地址可以在company1和company2注册,但就Symfony而言,它们是独立的用户。我有一个查看主机名的服务来确定公司。 FilterControllerEvent处理程序使公司对象在控制器中神奇地可用。

这一切都很顺利。

但是......那些公司有分歧。例如, company1 - division 1,

company1 - division 2,

company2 - division 3

对于大多数动作,divisionId将是第一个参数......

company1.example.com/1

company1.example.com/2

现在复杂化了。用户可能在不同的部门具有不同的角色。 company1的user1可能在1区有ROLE_BOSS,但在2区有ROLE_WORKER。

UserProvider从数据库加载角色。这是基于电子邮件地址和公司,但...它也可以基于URL参数?我想我需要将Request对象注入我的UserProvider并查看属性。这种方法有什么问题吗?这有点过于克拉吗?

我一直在努力寻找最好的方法。我的要求基本上是:

  • 为公司用户单一登录(基于电子邮件地址),即使他们访问多个部门并在这些部门担任不同的角色。

  • 公司不相关,因此请允许不同公司使用相同的电子邮件地址。如果用户确实在多家公司拥有帐户,那么他可以单独登录每个帐户,并使用书签或其他任何内容进行访问。对于用户来说,他们是独立的,无关的网站。

  • 用户应该可以在不同的部门之间进行分组。

  • Symfony防火墙系统应“正常工作”。 User1应该能够访问company1.example.com/1/BossStuff而不是仅仅基于我的UserProvider加载的角色的company1.example.com/2/BossStuff,而不是每个控制器操作中的繁琐的安全检查代码(已经完成了)

我考虑的其他方式是......

  • 每个部门都有一个独特的子域名。部门ID意味着公司ID,因此用户仍然可以是公司独有的。我们不再需要divisionId URL参数。问题是用户在同一公司的部门之间移动时需要登录。

  • 如上所述的分区的唯一子域,但是使PHP会话cookie .example.com而不是子域。这解决了在部门之间再次登录的需要,但如果你想在公司之间切换则会变得混乱。您无法继续登录company1和company2。

  • 再次,分区的唯一子域,子域的cookie,但有一些其他的身份验证机制,以便在登录company1-division1.example.com时,它会在.example.com上放置一个唯一的cookie,这样如果你那么访问company1-division2.example.com,它会读取该cookie并自动登录。可能会从安全的角度来看,但是可能会有点麻烦和可怕。我不确定我是否想去那里。

我已经阅读过有关身份验证提供程序,访问控制列表,选民等信息。我不认为他们在这方面对我有多大帮助。

感谢任何想法。

1 个答案:

答案 0 :(得分:0)

回答我自己的问题。这似乎工作正常。

总结一下,或许以更简单的方式...我在http://www.example.com有一个网站,在http://www.example.com/1http://www.example.com/2http://www.example.com/3等有几个子网站。我想要一个登录用户以在不同的子网站上拥有不同的角色。我的用户提供程序查看Request :: attributes-> get('_ route_params')以从URL获取子网站id参数。我的UserProvider :: loadUserByUsername和UserProvider :: refreshUser返回一个具有适合该子网站的角色的用户。

一个问题是AbstractToken序列化当前角色并将它们保存在会话中以便在下一个请求时恢复。这意味着只需在UserProvider :: refreshUser中返回不同的角色就不会刷新角色。此问题是此主题的主题:https://groups.google.com/forum/#!topic/symfony2/NDBb4JN3mNc。这可以通过确保在角色发生更改时User :: isEqualTo返回false来解决。在我的情况下,如果subsiteId已更改,则返回false。这迫使Symfony重新进行身份验证,因此在下次检查角色时重新加载角色。这是在明确调用SecurityContext :: isGranted或命中防火墙规则时。

首先让人感到有些不安的一件事是,如果您切换子网站而不检查角色(例如,转到公共页面),那么Symfony探查器会说“已验证:否”。检查角色时,这将更改为“是”。我认为这没关系。当重要的是,当我需要通过角色控制访问时,一切都会正确发生。