5

Ich mache REST API für meine JS getrieben App.Symfony2 App mit RESTful Authentifizierung, mit FOSRestBundle und FOSUserBundle

Während der Anmeldung wird das Login-Formular über AJAX an URL /rest/login meiner API gesendet.

  • Wenn die Anmeldung erfolgreich ist, gibt sie 204
  • Wenn es fehlschlägt, gibt sie 401

Während ich Firewalls für die API und die App selbst getrennt haben, teilen sie den gleichen Zusammenhang die sollte bedeuten, dass, wenn sich der Benutzer gegen die API authentifiziert, er auch gegen die App authentifiziert wird. Also, wenn der Server 204 zurückgibt, Seite wird neu geladen und es sollte Benutzer der App umleiten, weil er jetzt angemeldet ist.

Ich habe versucht, vorgefertigten check_login Seite des FOSUserBundle zu verwenden und darauf /rest/login dort.

login: 
    path: /rest/login 
    defaults: 
     _controller: FOSUserBundle:Security:check 
    methods: [ POST ] 

Das funktioniert nicht, weil es immer Umleitung zurückgibt, egal was. Ich habe die Dokumentation für Symfony gelesen und konnte nicht finden, wie man eine benutzerdefinierte check_login Seite erstellt. Was ich brauche, ist so etwas

use Symfony\Component\Security\Core\Exception\AuthenticationException; 
use FOS\RestBundle\Controller\Annotations\View;  

class SecurityController { 

    /** 
    * @View(statusCode=204) 
    */ 
    public function loginAction($username, $password) { 

     /* first I need to somehow authenticate user 
      using normal authentication, that I've set up */ 
     ... 

     /* Then I need to return 204 or throw exception, 
      based on result. 
      This is done using FOSRestBundle and it's 
      listeners. */ 

     if(!$succesful) { 
      throw new AuthenticationException(); 
     } 
    } 
} 

Ich habe keine Ahnung, wie das geht. Nichts, was ich in irgendeiner Dokumentation fand, half mir ein bisschen. Ich bin dankbar für jeden Vorschlag, der mich in die richtige Richtung weisen würde.


EDIT: Um weiter zu vereinfachen, was ich anstrebe. Ich möchte, dass mein Login genauso funktioniert wie normal form_login. Ich möchte nur die Antwort ändern, die es zurücksendet - anstatt Umleitung möchte ich 204 bei Erfolg und 401 bei Ausfall.

Antwort

12

Ich konnte eine einfache Lösung finden. Ich musste nur eine Klasse schreiben, die AuthenticationSuccessHandlerInterface und AuthenticationFailureHandlerInterface implementiert.

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 
use Symfony\Component\Security\Core\Exception\AuthenticationException; 
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; 
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; 

class AuthenticationRestHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface { 

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { 
     return new Response('', Response::HTTP_UNAUTHORIZED); 
    } 

    public function onAuthenticationSuccess(Request $request, TokenInterface $token) { 
     return new Response('', Response::HTTP_NO_CONTENT); 
    } 
} 

Dann habe ich es als Dienst registriert und als Handler für die Firewall konfiguriert.

services: 
    security.authentication_rest_handler: 
    class: AuthenticationRestHandler 

security: 
    firewalls: 
    rest: 
     pattern: ^rest 
     context: app 
     form_login: 
     check_path: /rest/login 
     provider: fos_userbundle 
     failure_handler: inspireon.security.authentication_rest_handler 
     success_handler: inspireon.security.authentication_rest_handler 
     username_parameter: login 
     password_parameter: password 

Problem gelöst und keine komplizierten Authentifizierungs-Provider benötigt :-)

1

Ich habe Ihr Problem verstanden, weil ich durch eine ähnliche Situation, aber mit SOAP-Diensten passiert. In der Mitte konnte ich die Sicherheit wsse erneut suchen und Symfony2 bietet bereits eine Lösung

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

Es mit einem echten Token funktioniert und Sie können mit einem Benutzer in FOSUserBundle entsprechen. Der einzige Gedanke, den ich sehe, ist, dass das Feld "password", das Sie vergleichen möchten, dasselbe ist wie in der Datenbank (mit Verschlüsselung), dann habe ich beschlossen, ein extra Feld nur für diese Verwendung zu erstellen.

Ich hoffe, dass es Ihnen hilft.

Grüße

+0

Also, ich ganz neue benutzerdefinierte Authentifizierungsanbieter implementieren muß?Imo ist es ein bisschen übertrieben, weil alles, was ich ändern muss, das Verhalten des Zuhörers ist, 204/401 statt Redirect zu senden, nicht den ganzen Prozess. –