Symfony3 文档 WSSE 失败 "Cannot replace arguments if none have been configured yet"

标签 symfony wsse

按照此

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_securedWsseFactory 创建的定义首先生产。然后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::replaceArgumentindex_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::addArgumentDefinition::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/

相关文章:

java - 在java中使用wsdl、用户名和密码调用soap webservice

c# - 使用 C# 的基于 WSSE 的服务的客户端

带有命名 Assets 的 Symfony Assets ,在生产环境中转储两次?

symfony - 在 JMS Serializer 上反序列化期间构造对象

symfony - Symfony2中用于缓存的内部路由

php - 检查 WS* 服务器实现中的签名

Symfony2 通过集成测试的 API 对用户进行身份验证

php - 本地主机 NodeJS 和 PHP 在同一域中

symfony - 如何在Mink中配置curl参数?