2017-02-15 2 views
3

Ich habe ein Symfony 2.8 Projekt, in dem ich FOSUserBundle verwende. Die Authentifizierungsmethode FOSUser verwendet die Tabelle fos_user zum Identifizieren und Validieren der Anmeldeinformationen und des Schlüssels, der mit sha512 verschlüsselt wurde.FOSUserBundle mit zwei Authentifizierungsmethoden

Ist es möglich, einige Klassen zu ändern oder zu erweitern, so dass, falls es den Benutzer in der Tabelle fos_user nicht findet, suchen Sie in der Benutzertabelle, in der der Schlüssel mit md5 verschlüsselt ist?

Aktualisierung nach dem Sonnenuntergang von madshvero:

ich eine Benutzerklasse erstellt haben:

namespace AppBundle\Security\User; 

use Symfony\Component\Security\Core\User\UserInterface; 
use Symfony\Component\Security\Core\User\EquatableInterface; 

class WebserviceUser implements UserInterface, EquatableInterface 
{ 
    private $username; 
    private $password; 
    private $salt; 
    private $roles; 

    public function __construct($username, $password, $salt, array $roles) 
    { 
     $this->username = $username; 
     $this->password = $password; 
     $this->salt = $salt; 
     $this->roles = $roles; 
    } 

    public function getRoles() 
    { 
     return $this->roles; 
    } 

    public function getPassword() 
    { 
     return $this->password; 
    } 

    public function getSalt() 
    { 
     return $this->salt; 
    } 

    public function getUsername() 
    { 
     return $this->username; 
    } 

    public function eraseCredentials() 
    { 
    } 

    public function isEqualTo(UserInterface $user) 
    { 
     if (!$user instanceof WebserviceUser) { 
      return false; 
     } 

     if ($this->password !== $user->getPassword()) { 
      return false; 
     } 

     if ($this->salt !== $user->getSalt()) { 
      return false; 
     } 

     if ($this->username !== $user->getUsername()) { 
      return false; 
     } 

     return true; 
    } 
} 

Ich habe auch die Benutzer-Provider erstellt:

namespace AppBundle\Security\User; 

use AppBundle\Security\User\WebserviceUser; 
use Symfony\Component\Security\Core\User\UserProviderInterface; 
use Symfony\Component\Security\Core\User\UserInterface; 
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; 
use Symfony\Component\Security\Core\Exception\UnsupportedUserException; 

class WebserviceUserProvider implements UserProviderInterface 
{ 
    public function loadUserByUsername($username) 
    { 
     // make a call to your webservice here 
     $userData = true; 
     // pretend it returns an array on success, false if there is no user 

     if ($userData) { 
      $username = 'prueba'; 
      $password = 'e10adc3949ba59abbe56e057f20f883e'; // md5('123456') 
      $salt = '';`enter code here` 
      $roles = [ROLE_SUPER_ADMIN]; 
      // ... 

      return new WebserviceUser($username, $password, $salt, $roles); 
     } 

     throw new UsernameNotFoundException(
      sprintf('Username "%s" does not exist.', $username) 
     ); 
    } 

    public function refreshUser(UserInterface $user) 
    { 
     if (!$user instanceof WebserviceUser) { 
      throw new UnsupportedUserException(
       sprintf('Instances of "%s" are not supported.', get_class($user)) 
      ); 
     } 

     return $this->loadUserByUsername($user->getUsername()); 
    } 

    public function supportsClass($class) 
    { 
     return WebserviceUser::class === $class; 
    } 
} 

Und modifiziere die security.yml:

Natürlich habe ich verändern auch den services.yml den Dienst app.webservice_user_provider hinzuzufügen: Dienstleistungen: app.form.group: Klasse: AppBundle \ Formular \ GroupFormType tags: - { Name: form.type, alias: app_group_registration}

app.form.user: 
     class: AppBundle\Form\ProfileFormType 
     tags: 
      - { name: form.type, alias: app_user_profile } 

    app.webservice_user_provider: 
     class: AppBundle\Security\User\WebserviceUserProvider 

Dies getan, das Verhalten ist, dass das System den Zugriff für die Benutzer des fos_user Anbieter erlaubt, nicht aber für die Nutzer meines c ustom Anbieter. Was scheitert?

Das es das Protokoll:

[2017.02.16 11.37.08] request.INFO: Matched route "fos_user_security_check". { "Route_parameters": { "_ Controller": "AppBundle \ Controllers \ SecurityController :: checkAction", "_ Route": "fos_user_security_check"}, "request_uri": "http://127.0.0.1:8000/app_dev.php/login_check"} []

[2017-02-16 11:37:08] doctrine.DEBUG: SELECT t0.id_aspirante AS id_aspirante1, t0.correo AS correo2, t0.clave AS clave3, t0.status_cuenta AS status_cuenta4 FROM aspirantes2 t0 WHERE t0.correo = ? LIMIT 1 ["userFoo"] [] 

[2017-02-16 11:37:08] doctrine.DEBUG: SELECT t0.id_aspirante AS id_aspirante1, t0.correo AS correo2, t0.clave AS clave3, t0.status_cuenta AS status_cuenta4 FROM aspirantes2 t0 WHERE t0.correo = ? LIMIT 1 ["userFoo"] [] 

[2017-02-16 11:37:08] security.INFO: Authentication request failed. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationServiceException(code: 0): The user provider must return a UserInterface object. at /home/userx/projects/myproj/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php:94, Symfony\\Component\\Security\\Core\\Exception\\AuthenticationServiceException(code: 0): The user provider must return a UserInterface object. at /home/userx/projects/myproj/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php:86)"} [] 

[2017-02-16 11:37:08] security.DEBUG: Authentication failure, redirect triggered. {"failure_path":"/login"} [] 

[2017-02-16 11:37:08] request.INFO: Matched route "fos_user_security_login". {"route_parameters":{"_controller":"AppBundle\\Controller\\SecurityController::loginAction","_route":"fos_user_security_login"},"request_uri":"http://127.0.0.1:8000/app_dev.php/login"} [] 

[2017-02-16 11:37:08] security.INFO: Populated the TokenStorage with an anonymous Token. [] [] 

[2017-02-16 11:37:08] request.INFO: Matched route "_wdt". {"route_parameters":{"_controller":"web_profiler.controller.profiler:toolbarAction","token":"c368df","_route":"_wdt"},"request_uri":"http://127.0.0.1:8000/app_dev.php/_wdt/c368df"} [] 

[2017-02-16 11:37:08] security.INFO: Populated the TokenStorage with an anonymous Token. [] [] 

[2017-02-16 11:37:08] security.DEBUG: Access denied, the user is not fully authenticated; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403): Access Denied. at /home/userx/projects/myproj/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/AccessListener.php:70)"} [] 

[2017-02-16 11:37:08] security.DEBUG: Calling Authentication entry point. [] [] 

[2017-02-16 11:37:08] request.INFO: Matched route "fos_user_security_login". {"route_parameters":{"_controller":"AppBundle\\Controller\\SecurityController::loginAction","_route":"fos_user_security_login"},"request_uri":"http://127.0.0.1:8000/app_dev.php/login"} [] 

[2017-02-16 11:37:08] security.INFO: Populated the TokenStorage with an anonymous Token. [] [] 

Antwort

0

Nach dem Lesen der Dokumentation konnte ich die Logik der Authentifizierungsmethoden verstehen, und ich fand es bequemer und einfach um einen Authentifizierungsanbieter aus einer Datenbank für mein Projekt zu verwenden. Wirklich ist eine sehr einfache Lösung, die in dokumentiert ist: How to Load Security Users from the Database (the Entity Provider)

In meinem Fall für die Verwendung von FOSUserBundle sind es zwei Überlegungen:

  1. Sie müssen zwei Authentifizierungsmethoden existieren: die eine, die von FOSUserBundle und einem bereitgestellt von MyBundle.
  2. Der Authentifizierungsprozess sollte versuchen, den Benutzer in beiden Methoden zu authentifizieren.

Dazu abgesehen von den in How to Load Security Users from the Database (the Entity Provider) gegebenen Empfehlungen, müssen Sie einige Abschnitte von security.yml so modifizieren, dass sie so aussehen ::

encoders: 
    // The database method of FOSUserBundle 
    FOS\UserBundle\Model\UserInterface: 
     algorithm: sha512 
    // The data base method of mine 
    MyBundle\Entity\MyEntity: 
     //This values depends on how the keys were encrypted in the database 
     algorithm: md5 
     encode_as_base64: false 
     iterations: 0 

providers: 
    chain_provider: 
     chain: 
      providers: [fos_userbundle, aspirante_db] 

    fos_userbundle: 
     id: fos_user.user_provider.username 

    myentity_db: 
     entity: { class: MyBundle\Entity\MyEntity, property: username } 

firewalls: 
    main:                                
     pattern: ^/ 
     fr3d_ldap: ~ 
     form_login: 
      provider: chain_provider //This is the important change 
      check_path: /login_check 
      login_path: /login 
      always_use_default_target_path: true 
      default_target_path:/
     logout: 
      path: /logout 
      target: /login 
     anonymous: true 
    dev: 
     pattern: ^/(_(profiler|wdt)|css|images|js)/ 
     security: false 
    login: 
     pattern: ^/login$ 
     security: false 

Das ist alles. Ich hoffe, dass in Zukunft jemand diesen Posten nutzen kann. Vielen Dank an madshvero für seine Führung.

0

Sie tun können Dies geschieht durch Erstellen einer custom provider, die in beiden Tabellen nach dem Benutzer sucht und den gefundenen Benutzer zurückgibt.

Dann können Sie app/config/security.yml aktualisieren Sie Ihren Anbieter statt der von FOSUserBundle zu nutzen:

security: 
    providers: 
     fos_userbundle: 
      id: the.id.of.your.provider 
+0

Hallo madshvero, danke für die Antwort so schnell. Ich möchte wirklich nicht meinen Provider anstelle von FOSUser verwenden, ich möchte, dass der Nutzer sich zuerst den FOSUser-Anbieter ansieht und ob er nicht in meinem sucht. –

+0

Ist es eine Option, dass Ihr Provider den FOSUserBundle-Provider erweitert und zuerst überprüft, ob "parent :: loadUserByUsername" eine Ausnahme auslöst, und wenn ja, Ihre eigene Logik für die andere Tabelle verwendet? Sie könnten auch in Ihrem Provider den [user manager] (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Model/UserManager.php) verwenden, der im [provider im FOSUserBundle] verwendet wird (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Security/UserProvider.php) um die Benutzer zu sehen – madshvero

Verwandte Themen