Symfony 5.2.11:创建自定义访问决策管理器时出现问题
Symfony 5.2.11: Problem with creating Custom Access Decision Manager
我正在尝试通过在 Symfony 5.2 上实现 AccessDecisionManagerInterface
来创建自定义访问决策管理器。
Symfony 识别决策管理器并将其实例化,但它不会将 Voters 数组传递给决策管理器。所以它不能收集选票,但默认的决策管理器工作正常。我遵循了 Symfony 网站上提供的信息。我也已将决策管理器文件复制到我的 App\Security 并只是更改了 class+ 文件名,但它没有用。将自定义决策管理器添加到 service.yml
也没有帮助。
有没有人遇到过同样的问题?有机会修复它吗?
更新#1
参考问题https://github.com/symfony/symfony/issues/41123
我遇到了不同症状的这个问题!
虽然我知道该服务是自动注册的,但我在 service.yml:
中这样做了
App\Security\SpecialAccessDecisionManager:
class: App\Security\SpecialAccessDecisionManager
autowire: false
autoconfigure: false
public: false
然后我将决策管理器添加到 security.yml:
security:
access_decision_manager:
service: App\Security\SpecialAccessDecisionManager
如下所示,参数尚未传递给决策管理器:
[root@dev7 rouzonline.test]# bin/console debug:container debug.security.access.decision_manager.inner --show-arguments
// This service is a private alias for the service
// App\Security\SpecialAccessDecisionManager
Information for Service "App\Security\SpecialAccessDecisionManager"
===================================================================
Description of SpecialAccessDecisionManager
---------------- -------------------------------------------
Option Value
---------------- -------------------------------------------
Service ID App\Security\SpecialAccessDecisionManager
Class App\Security\SpecialAccessDecisionManager
Tags -
Public no
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired no
Autoconfigured no
---------------- -------------------------------------------
! [NOTE] The "debug.security.access.decision_manager.inner" service or alias has been removed or inlined when the
! container was compiled.
[root@dev7 rouzonline.test]#
当我使用默认 AccessDecisionManager 时,投票者通过了。我需要实施特殊授权,所以我需要创建自己的决策管理器。顺便说一下,我的决策管理器实现了 AccessDecisionManagerInterface
我也检查了 \SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass->process()
,当我的决策管理器设置时它没有被调用。
更新#2
为了测试,我临时改名为 default AccessDecisionManager.php 并放置了我的 decision manager,它出人意料地起作用了。但这不是解决方案。仍在寻找正确的解决方案。
谢谢大家的回复和帮助,我明白了。
解决方法
当 Symfony 编译代码时,它(不知何故)有自己的服务定义,所以它不会混淆。我将代码跟踪到已编译的缓存中,发现它无法确定我的 ADM 的服务定义。所以我改变了我的 service.yml
并定义参数如下:
security.access.decision_manager:
class: App\Security\SpecialAccessDecisionManager
arguments:
- []
- 'affirmative'
- false
- true
在vendor/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
里面我发现有参数替换,它通过数字枚举服务参数,这就是我添加未命名服务参数的原因。
$container->getDefinition('security.access.decision_manager')
->replaceArgument(0, new IteratorArgument($voterServices));
}
跟踪显示到目前为止,Symfony 正确收集了所有选民,因此不需要手动管理依赖项。
通过使用这个 service.yml,我不需要在 security.yml
中定义 access_decision_manager
。
发现问题后,我尝试使用access_decision_manager
但它导致了同样的错误,意味着它没有收到选民名单。然后我决定停止解决这个问题,因为它现在对我有用。
结论
我知道 AccessDecisionManager 在某种程度上是一个很深的 Symfony 概念,很少用于普通项目,但是:
- 文档没有充分涵盖这部分内容
- 当开发人员实现接口并将其注入 Symfony 时,它应该被视为与本机代码完全相同,或者提供足够的描述性日志或详细信息以显示违规行为
- 我解决问题的方法不标准,以后可能需要修改
- Symfony 在处理来自
security.yml
的 access_decision_manager
时出现异常
可能 Symfony 的这一部分需要复习。
我正在尝试通过在 Symfony 5.2 上实现 AccessDecisionManagerInterface
来创建自定义访问决策管理器。
Symfony 识别决策管理器并将其实例化,但它不会将 Voters 数组传递给决策管理器。所以它不能收集选票,但默认的决策管理器工作正常。我遵循了 Symfony 网站上提供的信息。我也已将决策管理器文件复制到我的 App\Security 并只是更改了 class+ 文件名,但它没有用。将自定义决策管理器添加到 service.yml
也没有帮助。
有没有人遇到过同样的问题?有机会修复它吗?
更新#1
参考问题https://github.com/symfony/symfony/issues/41123
我遇到了不同症状的这个问题!
虽然我知道该服务是自动注册的,但我在 service.yml:
中这样做了 App\Security\SpecialAccessDecisionManager:
class: App\Security\SpecialAccessDecisionManager
autowire: false
autoconfigure: false
public: false
然后我将决策管理器添加到 security.yml:
security:
access_decision_manager:
service: App\Security\SpecialAccessDecisionManager
如下所示,参数尚未传递给决策管理器:
[root@dev7 rouzonline.test]# bin/console debug:container debug.security.access.decision_manager.inner --show-arguments
// This service is a private alias for the service
// App\Security\SpecialAccessDecisionManager
Information for Service "App\Security\SpecialAccessDecisionManager"
===================================================================
Description of SpecialAccessDecisionManager
---------------- -------------------------------------------
Option Value
---------------- -------------------------------------------
Service ID App\Security\SpecialAccessDecisionManager
Class App\Security\SpecialAccessDecisionManager
Tags -
Public no
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired no
Autoconfigured no
---------------- -------------------------------------------
! [NOTE] The "debug.security.access.decision_manager.inner" service or alias has been removed or inlined when the
! container was compiled.
[root@dev7 rouzonline.test]#
当我使用默认 AccessDecisionManager 时,投票者通过了。我需要实施特殊授权,所以我需要创建自己的决策管理器。顺便说一下,我的决策管理器实现了 AccessDecisionManagerInterface
我也检查了 \SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass->process()
,当我的决策管理器设置时它没有被调用。
更新#2 为了测试,我临时改名为 default AccessDecisionManager.php 并放置了我的 decision manager,它出人意料地起作用了。但这不是解决方案。仍在寻找正确的解决方案。
谢谢大家的回复和帮助,我明白了。
解决方法
当 Symfony 编译代码时,它(不知何故)有自己的服务定义,所以它不会混淆。我将代码跟踪到已编译的缓存中,发现它无法确定我的 ADM 的服务定义。所以我改变了我的 service.yml
并定义参数如下:
security.access.decision_manager:
class: App\Security\SpecialAccessDecisionManager
arguments:
- []
- 'affirmative'
- false
- true
在vendor/symfony/security-bundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
里面我发现有参数替换,它通过数字枚举服务参数,这就是我添加未命名服务参数的原因。
$container->getDefinition('security.access.decision_manager')
->replaceArgument(0, new IteratorArgument($voterServices));
}
跟踪显示到目前为止,Symfony 正确收集了所有选民,因此不需要手动管理依赖项。
通过使用这个 service.yml,我不需要在 security.yml
中定义 access_decision_manager
。
发现问题后,我尝试使用access_decision_manager
但它导致了同样的错误,意味着它没有收到选民名单。然后我决定停止解决这个问题,因为它现在对我有用。
结论
我知道 AccessDecisionManager 在某种程度上是一个很深的 Symfony 概念,很少用于普通项目,但是:
- 文档没有充分涵盖这部分内容
- 当开发人员实现接口并将其注入 Symfony 时,它应该被视为与本机代码完全相同,或者提供足够的描述性日志或详细信息以显示违规行为
- 我解决问题的方法不标准,以后可能需要修改
- Symfony 在处理来自
security.yml
的
access_decision_manager
时出现异常
可能 Symfony 的这一部分需要复习。