2017-09-22 1 views
4

Im Anschluss an dieseSymfony3 Docs WSSE fail "Kann nicht Argumente ersetzen, wenn noch keiner konfiguriert wurden"

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

Ergebnisse in

Service "security.authentication.provider.wsse.wsse_secured": Argumente können nicht ersetzt werden, wenn noch keine konfiguriert wurden.

Ich kann nirgendwo etwas über diesen Fehler finden. Dies verwendet den WSE-Code des Dokuments und schlägt fehl.

Diese Repo zeigt es https://github.com/jakenoble/wsse_test Versagen

Ich mag es Bundle schließlich mit dem FOS Benutzer erhalten zu arbeiten. Aber ich kann es nicht mit einer einfachen Symfony3-Installation arbeiten, so dass FOS User Bundle im Moment nicht in Frage kommt.

ein wenig herum gegraben Nachdem ...

Es ist ein eine arg an Elemente index_0 auf Klasse Symfony\Component\DependencyInjection\ChildDefinition das Objekt für die ARG bei Elemente index_0 eine ID von fos_user.user_provider.username_email hat.

Der Replace-Aufruf versucht dann, die Argumente von fos_user.user_provider.username_email zu bekommen, aber es gibt keine. Dann tritt der Fehler auf.

Irgendwelche Ideen?

Antwort

0

EDIT: (deleted den vorherigen Inhalt aufgrund der Kommentar)

Ich sehe Sie nicht FOSUserBundle verwenden, die Dinge mehr comples macht. Ich habe noch keine PR gemacht.

Ich denke, Sie fehlen custom user entity. (Siehe den Link, den ich zur Verfügung gestellt habe, um eine eigene Entität zu erstellen - meine PR wäre diesen Zeilen ähnlich, wenn Sie keine eigene Entity mit meiner Beschreibung und dem Link PR erstellen können, aber das dauert länger).

Die Schritte müssen Sie nehmen:

  1. über src/AppBundle/Entity/User.php
  2. Erstellen Sie Ihre eigenen User-Einheit DB über php bin/console doctrine:schema:update --force erstellen Tabelle
  3. konfigurieren Security Ihre Entity zu laden - use AppBundle\Entity\User;
  4. Dann Sie haben Erstelle deinen eigenen Benutzer. Dies kann schwierig sein, siehe password encoding für mehr.
  5. (optional) interaktive Benutzer Verbieten Wenn Sie mit
  6. Benutzernamen anmelden möchten oder eine E-Mail Sie Custom Query to Load the User

Diese Schritte sollten genug sein, erstellen Sie Ihre eigenen Benutzer Entity zu erstellen, und Sie haben nicht den FOSUserBundle zu verwenden.

+0

Haben Sie dieses Repo gezogen und versuchen, es zu reparieren? Weil nichts in Ihrer Antwort die grundlegende Implementierung aus dem Repo beeinflussen würde. Ich habe eine Version, die FOS User Bundle verwendet, aber es funktioniert nicht. Es hat die Konfiguration bereits an Ort und Stelle. –

+0

@JakeN: Bitte sehen Sie meine Bearbeitung. Ich habe die Antwort komplett geändert. – tukan

0

EDIT:

Ok, so etwas Quellcode lesen, und in ChildDefinition:100 können Sie sehen, dass Argumente werden auch $name durch Argument der indiziert. So muss es sein, dass zur Kompilierzeit Argumente von autodirekten Diensten mit ihren benannten Indizes anstelle von nummerierten Indizes übergeben werden.

WsseFactory.php

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

so sollte Argument durch seinen Namen referenziert werden:

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

Nach dieser Änderung werden Sie neue Ausnahmefehler erhalten, die besagt, dass es nicht möglich ist $authenticationManager in WsseListener autowire Service von seiner Schnittstelle. Sie können es einfach zu beheben, indem Alias ​​für diese Schnittstelle in Ihrem services.yml Angabe:

Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface: '@security.authentication.manager' 

Ich denke, das Problem mit neuer autowire Funktion verwendet ist, werde ich versuchen, es zu untersuchen später, warum es so ist.

Vorerst können Sie alte Art und Weise verwenden, um Dienste zu definieren:

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 

in WsseFactory.php, folgenden Zeilen:

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

übersetzt in:

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

3

Die in diesem Moment sehen aus wie die Provider-Definition nicht über die autowired Argumente bereit, vielleicht auf die auftragsbezogene, in dem die „CompilerPass“ verarbeitet werden, jetzt Sie es mit diesen kleinen Tweaks lösen können:

Änderung dieser Linie in WsseFactory.php:

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

von:

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

und fügen Sie diesen Alias ​​zu 012.die autowired Argumente des neuen Provider abzuschließen:

Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface: '@security.authentication.manager' 
0

Es scheint, das Problem ist, weil meine config in services.yml vor den neuen Auto-Verkabelung Sachen kam.

bewegen So einfach unter die automatische Verdrahtung es behebt.

+0

Sicher?Ich habe versucht, es unter der Autowiring-Konfiguration zu bewegen und das Problem besteht weiter – yceruto

+0

Das reparierte es für mich, verwende ich es jetzt –

3

TL; DR Ihre Service-Definitionen unter den autoloading Definitionen in services.yml verschieben und ändern Sie den Code WsseFactory zu

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

Vollständige Erklärung. Der erste Fehler im bereitgestellten Code besteht darin, dass die Definitionen der Dienste den Autoloading-Zeilen vorangehen. Das automatische Laden überschreibt einfach die vorherigen Definitionen und verursacht den Fehler AuthenticationManagerInterface. Durch Verschieben der folgenden Definitionen wird das Problem behoben. Die andere Möglichkeit, das Problem zu beheben, sind Aliasnamen wie @yceruto und @gintko.

Aber nur dieser Zug wird den Code trotz Ihrer Antwort nicht funktionieren lassen. Sie haben wahrscheinlich nicht bemerkt, wie etwas anderes geändert wurde, damit es funktioniert.

Das zweite Problem, der Fehler replaceArgument, bezieht sich auf Symfonys Reihenfolge der Container-Kompilierung, wie richtig angenommen wurde. Die Bestellung wird in der PassConfig Klasse definiert:

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

ich die irrelevanten Pässe weggelassen. Die von der WsseFactory erstellte security.authentication.provider.wsse.wsse_secured-Definition wird zuerst erstellt. Dann ResolveDefinitionTemplatesPass statt, und wird versuchen, die Argumente der Definition zu ersetzen und erhöhen die Cannot replace arguments Ausnahme Sie bekam:

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

Das Problem erscheint Ursache der Pass Definition::replaceArgument für index_0 nennen. Da die Elterndefinition kein Argument an Position 0 hat, weder in der früheren services.xml noch in der festen. AutowirePass wurde noch nicht ausgeführt, die automatisch generierten Definitionen haben keine Argumente, die manuelle Definition hat nur das Argument $cachePool.

Also das Problem beheben Sie lieber verwenden:

->setArgument(0, new Reference($userProvider)); //proposed by @yceruto 
->replaceArgument('$userProvider', new Reference($userProvider)); //proposed by @gintko 
->setArgument('$userProvider', new Reference($userProvider)); // by me 

Alle von ihnen werden die Anrufe von Definition::addArgument oder Definition::setArgument mit sich bringen und ausarbeitet. Es gibt nur den kleinen Unterschied: - setArgument(0, ... konnte für einige andere Szenarien nicht funktionieren; - Ich mag ->setArgument('$userProvider' mehr als ->replaceArgument('$userProvider' wegen Semantik. Nichts zu ersetzen noch!

Hoffe die Details, warum das Problem jetzt klar erscheint.

PS. Es gibt auch einige andere lustige Wege, um das Problem zu überwinden.

Befestigen Sie die Config ein wenig:

AppBundle\Security\Authentication\Provider\WsseProvider: 
    arguments: 
     0: '' 
     $cachePool: '@cache.app' 
    public: false 

Oder einen Alias ​​von Symfony\Component\Security\Core\User\UserProviderInterface Set für Sie die autowire den Rest erledigen zu lassen.

$container 
     ->setDefinition($providerId, new ChildDefinition(WsseProvider::class)) 
    // ->replaceArgument(0, new Reference($userProvider)) 
    ; 
    $container 
     ->setAlias('Symfony\Component\Security\Core\User\UserProviderInterface',$userProvider) 
    ; 
Verwandte Themen