在 symfony3 中在身份验证或重写 /login_check 之前收听请求

listen to request before authentication or rewrite /login_check in symfony3

我正在尝试注册一个将在 /login_check 尝试登录用户之前调用的 eventListener。

我正在编写 DDoS 保护,每次尝试都会在数据库中记录(日期,user_id,is_failure),如果用户有超过 N 次错误登录尝试,我会生成一个令牌通过电子邮件发送到正确的用户电子邮件。任何没有此令牌的人都将被禁止在 10 分钟内尝试再次登录。

要继续,我需要:

我没有找到关于 "pre_authentication" 的任何事件,你有解决方案吗?

我不会在存储库方法中编写代码来拉用户,这不是它的位置。

谢谢

几天前我遇到了类似的问题。就像你说的那样,我找不到合适的 "pre_authentication" 甚至在尝试身份验证之前我也可以执行我的检查。 (AuthenticationSuccess 和 AuthenticationFailure Handler 在我的案例中不是一个选项,因为我想在尝试之前阻止尝试)

但最后我找到了一种对我的情况有效的方法(虽然可能有更好的方法但我找不到)。

如果您的应用程序使用默认的 username/password 身份验证,您可以这样做:

  1. 扩展 UsernamePasswordFormAuthenticationListener

    class UsernamePasswordFormAuthenticationListener extends \Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener
    
    {
        /** @var EntityManagerInterface */
        protected $entityManager;
    
        /**
         * setter is called through DI container
         *
         * @param EntityManagerInterface $entityManager
         */
        public function setEntityManager(EntityManagerInterface $entityManager)
        {
            $this->entityManager = $entityManager;
        }
    
        /**
         *
         * @param Request $request
         *
         * @return null|RedirectResponse|\Symfony\Component\HttpFoundation\Response|\Symfony\Component\Security\Core\Authentication\Token\TokenInterface
         */
        protected function attemptAuthentication(Request $request)
        {
            //do your logic and whatnot here
            // i.E. return a redirect repsonse if the token is needed but missing 
    
            return parent::attemptAuthentication($request);
        }
    
    }
    
  2. 覆盖你原来的服务services.yml

    security.authentication.listener.form:
        class: AppBundle\Listener\UsernamePasswordFormAuthenticationListener
        parent: security.authentication.listener.abstract
        abstract: true
        calls: [ [setEntityManager, ["@doctrine.orm.entity_manager"]] ] 
    

(这里使用 setter 注入,因为构造函数需要大量参数)

也许这种方法可以满足您的需求,没有人有更好的主意