Symfony3 Docs WSSE fail "Cannot replace arguments if none have been configured yet"



遵循此

http://symfony.com/doc/current/security/custom_authentication_provider.html

导致

service" security.authentication.provider.wsse.wsse_secured":如果没有配置,则不能替换参数。

我在任何地方都找不到有关此错误的任何信息。这使用了DOC的WSSE代码,并且失败了。

此仓库显示失败https://github.com/jakenoble/wsse_test

我想最终与FOS用户捆绑包一起使用。但是我无法与基本的Symfony3安装一起使用,因此FOS用户捆绑包目前不可能。

有点挖...

SymfonyComponentDependencyInjectionChildDefinition上的元素 index_0上有一个arg,在元素 index_0处的arg对象具有 fos_user.user_provider.username_email的ID。

替换呼叫然后尝试获取fos_user.user_provider.username_email的参数,但没有。然后发生错误。

有什么想法?

tl; dr services.yml中的自动加载定义下方移动服务定义,然后更改WsseFactory代码到

    $container
        ->setDefinition($providerId, new ChildDefinition(WsseProvider::class))
        ->setArgument('$userProvider', new Reference($userProvider))
    ;

完整说明。提供的代码中的第一个错误是服务定义预先启动自动加载线。自动加载将仅覆盖先前的定义,并导致AuthenticationManagerInterface故障。移动下面的定义将解决该问题。解决该问题的另一种方法是@yceruto和@gintko指向的别名。

,尽管您的答案,但只有这一举动不会使代码工作。您可能没有注意到如何改变其他事情以使其正常工作。

第二个问题是replaceArgument的失败,与正确假定的Symfony的集装箱汇编顺序有关。该订单在PassConfig类中定义:

$this->optimizationPasses = array(array(
        new ExtensionCompilerPass(),
        new ResolveDefinitionTemplatesPass(),
        ...
        $autowirePass = new AutowirePass(false),
        ...
    ));

我省略了无关的通行证。WsseFactory创建的security.authentication.provider.wsse.wsse_secured定义首先产生。然后将进行ResolveDefinitionTemplatesPass,并尝试替换定义的参数并提高您获得的Cannot replace arguments例外:

    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);
        }
    }

问题将出现,因为通行证将为index_0调用Definition::replaceArgument。由于父定义在以前的services.xml中或固定固定的位置0中没有参数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, ...不能在其他情况下使用; - 由于语义,我比->replaceArgument('$userProvider'更喜欢->setArgument('$userProvider'。尚无替换!

希望详细信息为什么现在出现问题。

ps。也很少有其他有趣的方法来克服这个问题。

修复配置:

AppBundleSecurityAuthenticationProviderWsseProvider:
    arguments:
        0: ''
        $cachePool: '@cache.app'
    public: false

或设置SymfonyComponentSecurityCoreUserUserProviderInterface的别名,让自动射击为您完成。

    $container
        ->setDefinition($providerId, new ChildDefinition(WsseProvider::class))
    //    ->replaceArgument(0, new Reference($userProvider))
    ;
    $container
        ->setAlias('SymfonyComponentSecurityCoreUserUserProviderInterface',$userProvider)
    ;

此时,提供商定义还没有准备好自动参数,也许与现在处理" CompilerPass"的顺序有关您可以通过这些小调整来解决它:

WsseFactory.php中更改此行:

->replaceArgument(0, new Reference($userProvider))

->setArgument(0, new Reference($userProvider))

并将此别名添加到services.yml中以完成新提供商的自动参数:

SymfonyComponentSecurityCoreAuthenticationAuthenticationManagerInterface: '@security.authentication.manager'

编辑:(由于注释而删除了先前的内容)

我看到您不使用fosuserbundle,这使事情变得更加糟糕。我还没有创建PR。

我认为您缺少自定义用户实体。(请参阅我为创建自己的实体提供的链接 - 如果您无法使用我的描述和我提供的PR的链接创建自己的实体,那么我的PR将与这些行相似,但这将需要更长的时间)。

您必须采取的步骤:

  1. 通过src/AppBundle/Entity/User.php
  2. 创建自己的用户实体
  3. 通过php bin/console doctrine:schema:update --force创建DB表
  4. 配置Security加载您的Entity -use AppBundleEntityUser;
  5. 然后,您必须创建自己的用户。这可能很棘手,请参阅密码编码更多。
  6. (可选)禁止交互式用户,如果您想使用
  7. 登录
  8. 用户名或电子邮件您可以创建Custom Query to Load the User

这些步骤应该足以让您创建自己的用户实体,而您不必使用FosuserBundle。

编辑:

好吧,请阅读一些源代码,在ChildDefinition:100中,您可以看到,参数也由参数的$name索引。因此,必须在编译时通过其命名索引,而不是编号的索引。

WsseFactory.php

->replaceArgument(0, new Reference($userProvider));

因此,应以其名称引用参数:

->replaceArgument('$userProvider', new Reference($userProvider));

此更改后,您将获得新的异常错误,该错误表示无法通过其接口在WsseListener中自动化$authenticationManager。您可以通过在services.yml中指定该接口的别名来修复它:

SymfonyComponentSecurityCoreAuthenticationAuthenticationManagerInterface: '@security.authentication.manager'

我想这个问题与新的autowire功能有关,我将稍后尝试调查为什么它是这样的。

目前,您可以使用旧方法来定义服务:

services.yml:

app.security.wsse_provider:
    class: AppBundleSecurityAuthenticationProviderWsseProvider
        arguments:
            - ''
            - '@cache.app'
        public: false
app.security.wsse_listener:
    class: AppBundleSecurityFirewallWsseListener
    arguments: ['@security.token_storage', '@security.authentication.manager']
    public: false

在wssefactory.php中,以下行:

new ChildDefinition(WsseFactory::class);
new ChildDefinition(WsseListener::class);

翻译成:

new ChildDefinition('app.security.wsse_provider');
new ChildDefinition('app.security.wsse_listener');

似乎问题是因为我的config in services.yml是在新的自动布线之前出现的。

因此,简单地将其移动在自动接线下方。

相关内容

  • 没有找到相关文章

最新更新