按照此
http://symfony.com/doc/current/security/custom_authentication_provider.html
结果是
Service "security.authentication.provider.wsse.wsse_secured": Cannot replace arguments if none have been configured yet.
我在任何地方都找不到有关此错误的任何信息。这使用了文档的 WSSE 代码,但它失败了。
这个 repo 显示它失败 https://github.com/jakenoble/wsse_test
我想让它最终与 FOS 用户包一起工作。但是我不能让它与基本的 Symfony3 安装一起工作,所以 FOS User Bundle 目前是不可能的。
挖了一点...
元素
index_0
处有一个参数上课 Symfony\Component\DependencyInjection\ChildDefinition
元素 index_0
处 arg 的对象有一个 ID fos_user.user_provider.username_email
.然后替换调用尝试获取
fos_user.user_provider.username_email
的参数。 ,但没有。然后出现错误。有任何想法吗?
最佳答案
TL;博士 将您的服务定义移到 services.yml
中的自动加载定义下方并更改 WsseFactory
编码到
$container
->setDefinition($providerId, new ChildDefinition(WsseProvider::class))
->setArgument('$userProvider', new Reference($userProvider))
;
完整的解释。
提供的代码中的第一个错误是服务定义在自动加载行之前。自动加载只会覆盖之前的定义并导致
AuthenticationManagerInterface
失败。移动下面的定义将解决这个问题。解决问题的另一种方法是@yceruto 和@gintko 指出的别名。但是,尽管有您的回答,但只有这一举措不会使代码起作用。您可能没有注意到如何更改其他内容以使其工作。
第二个问题,
replaceArgument
失败, 与正确假设的 Symfony 的容器编译顺序有关。订单在 PassConfig
中定义类(class):$this->optimizationPasses = array(array(
new ExtensionCompilerPass(),
new ResolveDefinitionTemplatesPass(),
...
$autowirePass = new AutowirePass(false),
...
));
我省略了不相关的通行证。
security.authentication.provider.wsse.wsse_secured
由 WsseFactory
创建的定义首先生产。然后ResolveDefinitionTemplatesPass
将发生,并将尝试替换定义的参数并引发 Cannot replace arguments
你得到的异常(exception): foreach ($definition->getArguments() as $k => $v) {
if (is_numeric($k)) {
$def->addArgument($v);
} elseif (0 === strpos($k, 'index_')) {
$def->replaceArgument((int) substr($k, strlen('index_')), $v);
} else {
$def->setArgument($k, $v);
}
}
这个问题会出现,因为pass会调用
Definition::replaceArgument
为 index_0
.由于父定义在前 services.xml
中都没有位置 0 的参数。也不在固定的。 AutowirePass
尚未执行,自动生成的定义没有参数,手动定义的名称为 $cachePool
仅论据。所以要解决这个问题,你可以使用:
->setArgument(0, new Reference($userProvider)); //proposed by @yceruto
->replaceArgument('$userProvider', new Reference($userProvider)); //proposed by @gintko
->setArgument('$userProvider', new Reference($userProvider)); // by me
所有这些都需要调用
Definition::addArgument
或 Definition::setArgument
并且会解决。只有一点点区别:-
setArgument(0, ...
不能用于其他一些场景;- 我喜欢
->setArgument('$userProvider'
超过->replaceArgument('$userProvider'
由于语义。还没有什么可以更换的!希望问题出现的细节现在清楚。
附注。 还有一些其他有趣的方法可以解决这个问题。
稍微修复一下配置:
AppBundle\Security\Authentication\Provider\WsseProvider:
arguments:
0: ''
$cachePool: '@cache.app'
public: false
或者设置别名
Symfony\Component\Security\Core\User\UserProviderInterface
让 autowire 为您完成剩下的工作。 $container
->setDefinition($providerId, new ChildDefinition(WsseProvider::class))
// ->replaceArgument(0, new Reference($userProvider))
;
$container
->setAlias('Symfony\Component\Security\Core\User\UserProviderInterface',$userProvider)
;
关于Symfony3 文档 WSSE 失败 "Cannot replace arguments if none have been configured yet",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46368485/