Symfony3文件WSSE失败“;如果尚未配置任何参数,则无法替换参数";
此后 导致 服务“security.authentication.provider.wsse.wsse_securied”:如果尚未配置任何参数,则无法替换参数 我在任何地方都找不到关于这个错误的任何信息。这将使用文档的WSSE代码,但失败 这一回购协议表明它失败了 我想让它最终与FOS用户包一起工作。但我无法让它与基本的Symfony3安装一起工作,所以FOS用户包目前是不可能的 在附近挖了一点 类Symfony3文件WSSE失败“;如果尚未配置任何参数,则无法替换参数";,symfony,wsse,Symfony,Wsse,此后 导致 服务“security.authentication.provider.wsse.wsse_securied”:如果尚未配置任何参数,则无法替换参数 我在任何地方都找不到关于这个错误的任何信息。这将使用文档的WSSE代码,但失败 这一回购协议表明它失败了 我想让它最终与FOS用户包一起工作。但我无法让它与基本的Symfony3安装一起工作,所以FOS用户包目前是不可能的 在附近挖了一点 类Symfony\Component\DependencyInjection\ChildDefi
Symfony\Component\DependencyInjection\ChildDefinition
上有一个arg at元素index\u 0
的arg at元素对象的id为fos\u user.user\u provider.username\u email
然后replace调用尝试获取fos\u user.user\u provider.username\u email的参数,但没有参数。然后发生错误
有什么想法吗?编辑:(由于评论,删除了以前的内容)
我知道你没有使用FOSUserBundle使事情变得更复杂。我还没有创建公关
我想你失踪了。(请参阅我为创建您自己的实体提供的链接-如果您无法使用我的描述和我将提供的PR链接创建您自己的实体,我的PR将类似于这些行,但这将需要更长的时间)
您必须采取的步骤:
src/AppBundle/entity/User.php创建您自己的用户实体
php bin/console原则创建数据库表:schema:update--force
安全性
以加载您的实体
-使用AppBundle\Entity\User代码>
自定义查询以加载用户
$name
索引。因此,在编译时,自动连线服务的参数必须与其命名索引(而不是编号索引)一起传递
WsseFactory.php
->replaceArgument(0, new Reference($userProvider));
所以参数应该由它的名称引用:
->replaceArgument('$userProvider', new Reference($userProvider));
此更改后,您将获得新的异常错误,这表示无法通过其接口在WsseListener
服务中自动连线$authenticationManager
。您只需在服务中为该接口指定别名即可解决此问题。yml
:
Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface: '@security.authentication.manager'
我猜这个问题与新的
autowire
功能有关,稍后我将尝试研究它为什么会这样
现在,您可以使用旧方法定义服务:
services.yml:
app.security.wsse_provider:
class: AppBundle\Security\Authentication\Provider\WsseProvider
arguments:
- ''
- '@cache.app'
public: false
app.security.wsse_listener:
class: AppBundle\Security\Firewall\WsseListener
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');
此时看起来,提供程序定义没有准备好自动连接参数,可能与“CompilerPass”的处理顺序有关,现在您可以通过以下小调整来解决它: 在
WsseFactory.php
中更改此行:
->replaceArgument(0, new Reference($userProvider))
作者:
并将此别名添加到services.yml
以完成新提供者的自动连接参数:
Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface: '@security.authentication.manager'
问题似乎是因为我在services.yml中的配置出现在新的自动布线之前
因此,只需将其移动到自动布线下方即可修复它。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\u securied
定义。然后将发生ResolveDefinitionTemplatesPass
,并将尝试替换定义的参数,并引发您遇到的无法替换参数
异常:
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);
}
}
该问题将出现,因为该过程将调用索引0
的定义::replaceArgument
。因为父定义在前一个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'
),这是因为语义原因。还没有什么可以替换的
希望问题出现的细节现在清楚了
PS.还有一些其他有趣的方式可以让你轻松一下
->setArgument(0, new Reference($userProvider)); //proposed by @yceruto
->replaceArgument('$userProvider', new Reference($userProvider)); //proposed by @gintko
->setArgument('$userProvider', new Reference($userProvider)); // by me
AppBundle\Security\Authentication\Provider\WsseProvider:
arguments:
0: ''
$cachePool: '@cache.app'
public: false
$container
->setDefinition($providerId, new ChildDefinition(WsseProvider::class))
// ->replaceArgument(0, new Reference($userProvider))
;
$container
->setAlias('Symfony\Component\Security\Core\User\UserProviderInterface',$userProvider)
;