2017-11-28 11 views
0

私はFOSユーザバンドルを使用しています。私は自分のパラメータに使用する別のエンティティ/テーブルのレコードから "maxLoginAttempts"という値を使用する必要があります。ORMデータベースのパラメータを使用するFOSユーザバンドル

エンティティはパラメータと呼ばれます。これは私の現在のコードなので、データベースから値の5を変更したいと思います。

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use FOS\UserBundle\Model\User as BaseUser; 

/** 
* @ORM\Entity 
* @ORM\Table(name="`user`") 
*/ 
class User extends BaseUser 
{ 
    /** 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * @ORM\Column(type="integer") 
    */ 
    protected $id; 

    ... 

    public function isAccountNonLocked() 
    { 
     if($this->getLoginAttempts() >= 5) { 
      return false; 
     } else { 
      return true; 
     } 
    } 
} 

私のようなものを想像:

$this->em->getRepository('AppBundle:Parameters') 
     ->findOneBy(['name' => 'maxLoginAttempts']); 
明らか

を今私は、リポジトリにアクセスすることはできません。私がコントローラにいないので、エンティティの関数の内部からこれらの値をどのように使用すべきかはわかりません。

答えて

0

最後に、解決策は同じ機能を持つ別の機能を使用してUserCheckerをオーバーライドすることでした。

<?php 

namespace AppBundle\Checker; 

use Doctrine\ORM\EntityManagerInterface; 
use Symfony\Component\Security\Core\Exception\CredentialsExpiredException; 
use Symfony\Component\Security\Core\Exception\DisabledException; 
use Symfony\Component\Security\Core\Exception\LockedException; 
use Symfony\Component\Security\Core\User\AdvancedUserInterface; 
use Symfony\Component\Security\Core\User\UserChecker as BaseUserChecker; 
use Symfony\Component\Security\Core\User\UserInterface; 

class UserChecker extends BaseUserChecker 
{ 
    private $em; 

    public function __construct(EntityManagerInterface $em) 
    { 
     $this->em = $em; 
    } 

    public function checkPreAuth(UserInterface $user) 
    { 
     //parent::checkPreAuth($user); 
     $maxMinutesLocked = $this->em->getRepository('AppBundle:Parameters')->findOneBy(array('name' => 'maxTimeLocked'))->getValue(); 

     if (!$user instanceof AdvancedUserInterface) { 
      return; 
     } 

     //So I just added a new function called isAccountLocked() to the User Entity that's a copy from isAccountNonLocked() but I could add a paramater 
     if ($user->isAccountLocked($maxMinutesLocked)) { 
      $ex = new LockedException('User account is locked.'); 
      $ex->setUser($user); 
      throw $ex; 
     } 

     if (!$user->isEnabled()) { 
      ... 
     } 
     if (!$user->isAccountNonExpired()) { 
      ... 
     } 
    } 

    public function checkPostAuth(UserInterface $user) 
    { 
     ... 
    } 
} 
0

おそらくEntityの概念を誤解:

クラス - 多くの場合、データを保持している基本的なクラスを意味し、「エンティティ」と呼ばれる - シンプルであり、あなたの中に必要とする製品のビジネス要件を満たすことができます応用。このクラスは、まだデータベースに永続化することはできません - それはちょうどEntityがちょうど概念であることを意味し、単純なPHPクラス

だ、これあなたが他のEntitiesやへのアクセスを持つことができませんクラス内のEntityManager

説明したメンバ関数のようなものを使用したい場合は、あなたは、引数としてmaxLoginAttemptsを渡す必要があります。

:あなたが設定 Entity最初から maxLoginAttemptsの値を取得して、確認したい Userオブジェクトにそれを使用する必要があります。この場合

public function isAccountNonLocked($maxLoginAttempts) 
{ 
    if($this->getLoginAttempts() >= maxLoginAttempts) { 
     return false; 
    } else { 
     return true; 
    } 
} 

$maxLoginAttempts = $this->em->getRepository('AppBundle:Parameters') 
     ->findOneBy(['name' => 'maxLoginAttempts']); 
$user = $this->em->getRepository('AppBundle:User')->find($userId); 
if ($user->isAccountNonLocked($maxLoginAttempts)) { 
    // do something 
} 
+0

この機能は、SymfonyのセキュリティコアとFOSUserBundleの内部で使用されていることに気付きましたか?私は確信していませんが、あなたが言ったようにそれほど簡単ではないと思います。別の答えを教えてください。 –

+0

あなたは確かに基本クラスで何もすることはできません。あなたの 'User'クラスでこのメソッドをオーバーライドしたと思います。あなたは持っていないのですか? – Azuloo

0

は、私はこれを解決するために、私見、より適切な方法を考えることができます。

ユーザエンティティは、追加のプロパティを持つことになります$ loginAttemptsこれは、ログインが失敗するたびにincrementLoginAttempts()メソッドによって増分されます。 ORMによって0に初期化され、isLocked()メソッドは5回試行したかどうかを示します。 SecuritySubscriberイベントにEventSubscriberを作成

その後
<?php 
// AppBundle/Entity/User.php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use FOS\UserBundle\Model\User as BaseUser; 

/** 
* @ORM\Entity 
* @ORM\Table(name="`user`") 
*/ 
class User extends BaseUser 
{ 
    /** 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * @ORM\Column(type="integer") 
    */ 
    protected $id; 
    public function __construct() 
    { 
     parent::__construct(); 
    } 

    /** 
    * @ORM\Column(type="integer",options={"default"=0}) 
    */ 
    private $loginAttempts; 

    ... 
    public function getLoginAttempts() 
    { 
     return $this->loginAttemps; 
    } 
    public function incrementLoginAttempts() 
    { 
     if($this->loginAttempts<5){ 
      $this->loginAttempts++; 
     } 
     return $this; 
    } 
    public function isLocked() 
    { 
     return ($this->loginAttempts == 5) 
    } 
    public function resetLoginAttempts() 
    { 
     $this->loginAttempts =0; 
     return $this; 
    } 

、およびincrementLoginAttemptsを発射()ログインに失敗するたびに、同じ時間チェックイン時にユーザーがすでにロックされているか、まだ

<?php 
// src/AppBundle/EventSubscriber/SecuritySubscriber.php 
namespace AppBundle\EventSubscriber; 

use AppBundle\Entity\User; 

class SecuritySubscriber implements EventSubscriberInterface 
{ 

    private $entityManager; 
    private $tokenStorage; 
    private $authenticationUtils; 

    public function __construct(EntityManager $entityManager, TokenStorageInterface $tokenStorage, AuthenticationUtils $authenticationUtils) 
    { 
     $this->entityManager = $entityManager; 
     $this->tokenStorage = $tokenStorage; 
     $this->authenticationUtils = $authenticationUtils; 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(
      AuthenticationEvents::AUTHENTICATION_FAILURE => 'onAuthenticationFailure', 
     ); 
    } 

    public function onAuthenticationFailure(AuthenticationFailureEvent $event) 
    { 
     $existingUser = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $username]); 

     if ($existingUser) { 
      $existingUser->incrementLoginAttempts(); 
      $this->entityManager->persist($existingUser); 
      $this->entityManager->flush(); 
      if($existingUser->isLocked()){ 
       // Do your logic here 
       // Do not forget to un $existingUser->resetLoginAttempts() when necessary 
      } 
     } 
    } 
} 

はサービスとして

# app/config/services.yml 
services: 
    app.security.authentication_event_listener: 
     class: AppBundle\EventSubscriber\SecuritySubscriber 
     arguments: 
      - "@doctrine.orm.entity_manager" 
      - "@security.token_storage" 
      - "@security.authentication_utils" 

P.Sを加入者を登録することを忘れないでくださいされていない場合:コードがテストされていません。

+0

FOSUserBundleはそれを私のために行います。今は、FOSUSerBundleを提供するisAccountNonLocked()のすべての機能を制御できます。ログインに5回失敗すると、アカウントは指定した時間(たとえば1時間)ロックされます。しかし、私の質問は、この機能を構築したり、それを修正することではありません。 問題は、このケースではbbddというテーブルから番号5を取得したいということです。私はこの数値を変数に置き換えて、コードからではなくデータベースから値を変更できるようにしたいと思います。 –

+0

あなたの場所では、これを設定変数としてparameters.ymlに入れ、ここで説明するようにロードして使用します。https://symfony.com/doc/3.3/best_practices/configuration.html db-1コントローラからentityManagerにアクセスし、maxLoginAttemtpsをUserエンティティメソッドへの引数として渡します。 2-またはFOSUserログインフォームを次のように定義します。サービスを作成し、そこにentityManagerを挿入し、それを使用してmaxLoginAttemtpsをUser Entityに渡します – MedUnes

関連する問題