2017-03-09 6 views
0

物事は以下のとおりです。 symfonyの3 FosUserBundle非ユニークユーザ名のログイン

  • FosUserBundleは(すべてのユーザーを取得します
    • 非ユニークユーザ名[完了]
    • ユニークユーザ名と電子メールの組み合わせユーザーのログイン時に)指定されたユーザー名でログインし、指定されたパスワードを持つユーザーがいるかどうかをチェックします(bcryptでハッシュされます)。ユーザーが見つかったときには、ユーザーをログに記録します。

    ユーザーORMのユーザー名フィールドをオーバーライドするだけで、ユーザー名を一意にすることは非常に簡単でした。しかし、我々は最後の2つのポイントを達成するための進め方にちょっと固執している。私たちはカスタムユーザプロバイダを作成し始めましたが、Symfony Securityは1人のユーザ(名前)しか扱えないようです。

    私たちを助けてくれる経験がある人はいますか?さらに情報やコードスニペットが必要な場合は、お尋ねください。前もって感謝します!

    +1

    IMOこれを達成するためにFOSUserBundleを使用しないでください。独自のUserBundleを作成する必要があります。 – Shady

    +0

    私たちは現在、独自のGuardを実装しようとしていますが、FOSUserBundleとうまく連携しているように見えます。ソース:http://symfony.com/doc/current/security/guard_authentication.html –

    +2

    同じユーザー名を持つ2人のユーザーが同じパスワードを共有している場合は、 – kero

    答えて

    1

    Symfony Securityモジュールのドキュメントを見て、わかりました。

    ユーザー名がユニークであるという事実を背景にSymfonyが完全に構築されているため、追加のフィールド(displayname)をUserモデルに追加しました。与えられたユーザー名を持つ最初のユーザーを常に取得しますが、これは私たちが望むものではありません。

    私たちは独自のGuard Authentication Systemを作成し始めましたが、調整が必要でしたが、これはかなり簡単でした。 これはうまくいっていましたが、組み込みのUsernamePasswordFormAuthenticationListenerで問題が発生しましたが、このリスナーはまだログインフォームからdisplaynameを取得していました。実際には、Symfonyがどのユーザを使うかを知るために、一意のユーザ名が必要です。

    標準のリスナーを拡張したカスタムリスナーを作成し、ユーザー名がログインフォームから取得されず、ユーザートークンから取得されていることを確認しました。

    私たちの流れは次のようになります。ユーザーがユーザー名(実際に彼の表示名)とパスワードを入力すると、システムはその表示名を持つすべてのユーザーを取得します。次に、これらのユーザーをループして、誰かがそのパスワードを持っているかどうかを確認します。その場合は、ユーザーを認証します。 ユーザが作成すると、管理者が表示名を入力すると、システムはこれをユーザ名として自動的に増やします。 (admin_1、admin_2、...)。

    私は@keroが真実だと言っているのか監視しなければなりませんが、Bcryptでは "123"のような単純なパスワードでもユーザーごとに違うハッシュになります。

    残っているのは、表示名と電子メールのの組み合わせがのUniqueConstraintを持つことだけです。 orm.xmlとフォームでこれがどのように達成できるのか分かっている人は、ありがとう。

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

    カスタムガード認証

    class Authenticator extends AbstractGuardAuthenticator 
    { 
        private $encoderFactory; 
        private $userRepository; 
        private $tokenStorage; 
        private $router; 
    
    public function __construct(EncoderFactoryInterface $encoderFactory, UserRepositoryInterface $userRepository, TokenStorageInterface $tokenStorage, Router $router) 
    { 
        $this->encoderFactory = $encoderFactory; 
        $this->userRepository = $userRepository; 
        $this->tokenStorage = $tokenStorage; 
        $this->router = $router; 
    } 
    
    /** 
    * Called on every request. Return whatever credentials you want, 
    * or null to stop authentication. 
    */ 
    public function getCredentials(Request $request) 
    { 
        $encoder = $this->encoderFactory->getEncoder(new User()); 
        $displayname = $request->request->get('_username'); 
        $password = $request->request->get('_password'); 
    
        $users = $this->userRepository->findByDisplayname($displayname); 
    
        if ($users !== []) { 
         foreach ($users as $user) { 
          if ($encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) { 
           return ['username' => $user->getUsername(), 'password' => $user->getPassword()]; 
          } 
         } 
        } else { 
         if ($this->tokenStorage->getToken() !== null) { 
          $user = $this->tokenStorage->getToken()->getUser(); 
    
          return ['username' => $user->getUsername(), 'password' => $user->getPassword()]; 
         } 
        } 
    
        return null; 
    } 
    
    public function getUser($credentials, UserProviderInterface $userProvider) 
    { 
        if ($credentials !== null) { 
         return $userProvider->loadUserByUsername($credentials["username"]); 
        } 
    
        return null; 
    } 
    
    public function checkCredentials($credentials, UserInterface $user) 
    { 
        if ($user !== null) { 
         return true; 
        } else { 
         return false; 
        } 
    } 
    
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) 
    { 
        return null; 
    } 
    
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception) 
    { 
        $exclusions = ['/login']; 
    
        if (!in_array($request->getPathInfo(), $exclusions)) { 
         $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception); 
         throw $exception; 
        } 
    } 
    
    /** 
    * Called when authentication is needed, but it's not sent 
    */ 
    public function start(Request $request, AuthenticationException $authException = null) 
    { 
        $data = array(
         // you might translate this message 
         'message' => 'Authentication Required' 
        ); 
    
        return new JsonResponse($data, Response::HTTP_UNAUTHORIZED); 
    } 
    
    public function supportsRememberMe() 
    { 
        return false; 
    } 
    } 
    

    カスタムリスナー

    class CustomAuthListener extends UsernamePasswordFormAuthenticationListener 
    { 
        private $csrfTokenManager; 
        private $tokenStorage; 
    
    public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null) 
    { 
        parent::__construct($tokenStorage, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array(
         'username_parameter' => '_username', 
         'password_parameter' => '_password', 
         'csrf_parameter' => '_csrf_token', 
         'csrf_token_id' => 'authenticate', 
         'post_only' => true, 
        ), $options), $logger, $dispatcher); 
    
        $this->csrfTokenManager = $csrfTokenManager; 
        $this->tokenStorage = $tokenStorage; 
    } 
    
    /** 
    * {@inheritdoc} 
    */ 
    protected function attemptAuthentication(Request $request) 
    { 
        if ($user = $this->tokenStorage->getToken() !== null) { 
         $user = $this->tokenStorage->getToken()->getUser(); 
         $username = $user->getUsername(); 
    
         if ($this->options['post_only']) { 
          $password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']); 
         } else { 
          $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); 
         } 
    
         if (strlen($username) > Security::MAX_USERNAME_LENGTH) { 
          throw new BadCredentialsException('Invalid username.'); 
         } 
    
         $request->getSession()->set(Security::LAST_USERNAME, $username); 
    
         return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey)); 
        } else { 
         return null; 
        } 
    } 
    } 
    

    リスナーサービス

    <service id="security.authentication.listener.form" class="Your\Path\To\CustomAuthListener" parent="security.authentication.listener.abstract" abstract="true" /> 
    
    関連する問題