2017-11-28 26 views
0

FOS User Bundle을 사용하고 있으며 매개 변수에 사용하는 다른 Entity/테이블의 레코드에서 "maxLoginAttempts"라는 값을 사용해야합니다.ORM 데이터베이스의 매개 변수를 사용하는 FOS 사용자 번들

매개 변수는 매개 변수라고합니다. 이것은 현재 코드이며 데이터베이스에서 값의 5를 변경하고 싶습니다. 분명히

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

지금 내가 저장소에 액세스 할 수 없습니다 :

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

내가 좋아하는 뭔가를 상상한다. 컨트롤러에 없기 때문에 엔티티의 함수 내부에서이 값을 어떻게 사용해야하는지 잘 모르겠습니다. 아마 Entity의 개념을 잘못 이해하면

답변

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 그냥 개념 것을 의미하는 간단한 PHP 클래스

이다, 그래서 당신은 다른 Entities 나에 액세스 할 수 없습니다 클래스 내부에서 EntityManager.

설명 된 멤버 함수와 같은 것을 사용하려는 경우 당신이 인수로 maxLoginAttempts을 통과해야합니다

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

당신이 먼저 설정 Entity에서 maxLoginAttempts의 값을 취득하고 목적에 사용하기 위해 필요한이 경우에 User 당신이 확인하고 싶은 :

$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의 Security Core 및 FOSUserBundle 내부에서 사용된다는 것을 알고 계셨습니까? 나는 잘 모르겠지만 당신이 말했듯이 그렇게 쉽지는 않다고 생각합니다. 제발 또 다른 대답을 알고 싶습니다. –

+0

기본 클래스에서는 아무 것도 할 수 없습니다. 나는 당신이 당신의'User' 클래스에서이 메소드를 오버라이드했다고 가정합니다. 너도 하나도 없어? – Azuloo

0

내가 더 적절한 방법, 이럴 생각할 수있는,이 문제를 해결하려면 다음

이용자 엔티티가 추가 속성이있을 것이다 $ loginAttempts이 로그인이 실패 할 때마다 incrementLoginAttempts() 메소드에 의해 증가됩니다. ORM을 통해 0으로 초기화되고 isLocked() 메소드는 5 회 시도했는지 여부를 알려줍니다. 그런 다음

<?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를()마다 로그인이 실패 SecuritySubscriber 이벤트에 EventSubscriber를 만들고, 화재, 동시에 검사에서 사용자가 이미 잠금되었거나 아직
<?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를 얻고 싶습니다.이 경우 매개 변수입니다. 이 숫자 5를 변수로 바꾸려면 코드가 아닌 데이터베이스에서 값을 변경할 수 있어야합니다. –

+0

당신의 장소에 config.yml을 config 변수로 넣고 여기에 설명 된대로로드하여 사용하십시오. db- 지속 값을 사용하는 경우 논리를 구현 한 방법에 따라 두 가지 방법이 있습니다. 1- 컨트롤러에서 entityManager에 액세스하고 maxLoginAttemtps를 User 엔터티 메서드에 대한 인수로 전달하십시오. 2- 또는 FOSUser 로그인 폼을 다음과 같이 정의합니다. 서비스를 만들고 entityManager를 삽입 한 다음이를 사용하여 maxLoginAttemtps를 사용자 엔터티에 전달합니다 – MedUnes