如何使用 Symfony Security 获得动态安全权限
How to get dynamic security privileges with Symfony Security
我需要在 Symfony 上的访问控制中添加自定义访问法,我试着解释一下。
我有一些客户的 Web 应用程序,当该客户拥有正确的插件时,我希望能够访问部分代码。这是我的客户:
namespace AppBundle\Entity;
class CustomerProfile{
private $id;
private $user;
private $plugins;
}
插件实体
namespace AppBundle\Entity;
class Plugin{
private $id;
private $name;
private $customerProfiles;
}
我对关系使用原则,所以我可以从客户那里得到他的插件。例如,我们有 2 个客户和 2 个插件:
AppBundle\Entity\CustomerProfile:
customer_1:
user: '@user_1'
plugins: ['@plugin_1','@plugin_2']
customer_2:
user: '@user_2'
plugins: ['@plugin_1']
AppBundle\Entity\Plugin:
plugin_1:
name: 'plugin 1'
plugin_2:
name: 'plugin 2'
在我的项目中,所有关于客户的代码都在 /customer 命名空间下,Symfony 之类的,并且一切正常。
access_control:
- { path: ^/customer, roles: ROLE_CUSTOMER }
但是,对于这个使用不同插件的客户,我会设置动态访问控制,但我不知道如何设置。我需要控制这样的东西:
access_control:
- { path: ^/code_for_plugin_1, roles: ROLE_CUSTOMER_WHIT_PLUGIN_1}
- { path: ^/code_for_plugin_2, roles: ROLE_CUSTOMER_WHIT_PLUGIN_2}
但我认为好的方法是设置 "sub role"(如果存在)为每个拥有插件的客户设置在该命名空间中访问的角色。
希望我说得够清楚,谢谢你的帮助。
我建议使用自定义选民而不是 access_control
和角色方法
我认为这对您的用例更灵活。您建议的解决方案需要
为每个插件生成一个角色 (ROLE_CUSTOMER_WHIT_PLUGIN_{X}
),以防万一
动态添加插件是行不通的。
查看 Symfony 文档中的 How to Use Voters to Check User Permissions 文章了解更多详细信息。
你基本上需要实现一个用户投票器,它会检查登录的用户是否有访问权限
请求的资源。在您的情况下,它看起来类似于:
/src/YourBundle/Controller/YourController.php
<?php
...
class YourController extends Controller
{
public function getFooAction($id)
{
$this->denyAccessUnlessGranted(YourVoter::VIEW_FOO);
// ...method logic
}
public function getBarAction($id)
{
$this->denyAccessUnlessGranted(YourVoter::VIEW_BAR);
// ...method logic
}
}
/src/YourBundle/Security/YourVoter.php
<?php
...
class YourVoter extends AbstractVoter
{
const VIEW_FOO = 'YOUR_VIEW_FOO';
const VIEW_BAR = 'YOUR_VIEW_BAR';
public function getVoterAttributes()
{
return [self::VIEW_FOO, self::VIEW_BAR,];
}
protected function supports($attribute, $subject)
{
...
}
protected function voteOnAttribute($attribute, $item, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
switch ($attribute) {
case self::VIEW_FOO:
return $this->canViewFoo($user);
case self::VIEW_BAR:
return $this->canViewBar($user);
}
throw new \Exception(sprintf(
'Invalid vote attribute "%s".',
$attribute
));
}
private function canViewFoo(User $user)
{
return $user->getProfile()->hasRoleFooXYZ()
}
private function canViewBar(User $user)
{
return $user->getProfile()->hasRoleBarXYZ()
}
}
我需要在 Symfony 上的访问控制中添加自定义访问法,我试着解释一下。 我有一些客户的 Web 应用程序,当该客户拥有正确的插件时,我希望能够访问部分代码。这是我的客户:
namespace AppBundle\Entity;
class CustomerProfile{
private $id;
private $user;
private $plugins;
}
插件实体
namespace AppBundle\Entity;
class Plugin{
private $id;
private $name;
private $customerProfiles;
}
我对关系使用原则,所以我可以从客户那里得到他的插件。例如,我们有 2 个客户和 2 个插件:
AppBundle\Entity\CustomerProfile:
customer_1:
user: '@user_1'
plugins: ['@plugin_1','@plugin_2']
customer_2:
user: '@user_2'
plugins: ['@plugin_1']
AppBundle\Entity\Plugin:
plugin_1:
name: 'plugin 1'
plugin_2:
name: 'plugin 2'
在我的项目中,所有关于客户的代码都在 /customer 命名空间下,Symfony 之类的,并且一切正常。
access_control:
- { path: ^/customer, roles: ROLE_CUSTOMER }
但是,对于这个使用不同插件的客户,我会设置动态访问控制,但我不知道如何设置。我需要控制这样的东西:
access_control:
- { path: ^/code_for_plugin_1, roles: ROLE_CUSTOMER_WHIT_PLUGIN_1}
- { path: ^/code_for_plugin_2, roles: ROLE_CUSTOMER_WHIT_PLUGIN_2}
但我认为好的方法是设置 "sub role"(如果存在)为每个拥有插件的客户设置在该命名空间中访问的角色。
希望我说得够清楚,谢谢你的帮助。
我建议使用自定义选民而不是 access_control
和角色方法
我认为这对您的用例更灵活。您建议的解决方案需要
为每个插件生成一个角色 (ROLE_CUSTOMER_WHIT_PLUGIN_{X}
),以防万一
动态添加插件是行不通的。
查看 Symfony 文档中的 How to Use Voters to Check User Permissions 文章了解更多详细信息。
你基本上需要实现一个用户投票器,它会检查登录的用户是否有访问权限 请求的资源。在您的情况下,它看起来类似于:
/src/YourBundle/Controller/YourController.php
<?php
...
class YourController extends Controller
{
public function getFooAction($id)
{
$this->denyAccessUnlessGranted(YourVoter::VIEW_FOO);
// ...method logic
}
public function getBarAction($id)
{
$this->denyAccessUnlessGranted(YourVoter::VIEW_BAR);
// ...method logic
}
}
/src/YourBundle/Security/YourVoter.php
<?php
...
class YourVoter extends AbstractVoter
{
const VIEW_FOO = 'YOUR_VIEW_FOO';
const VIEW_BAR = 'YOUR_VIEW_BAR';
public function getVoterAttributes()
{
return [self::VIEW_FOO, self::VIEW_BAR,];
}
protected function supports($attribute, $subject)
{
...
}
protected function voteOnAttribute($attribute, $item, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
switch ($attribute) {
case self::VIEW_FOO:
return $this->canViewFoo($user);
case self::VIEW_BAR:
return $this->canViewBar($user);
}
throw new \Exception(sprintf(
'Invalid vote attribute "%s".',
$attribute
));
}
private function canViewFoo(User $user)
{
return $user->getProfile()->hasRoleFooXYZ()
}
private function canViewBar(User $user)
{
return $user->getProfile()->hasRoleBarXYZ()
}
}