如何在用户被授予登录(登录前)之前进行一些安全检查?

时间:2016-12-11 13:41:53

标签: php authentication login symfony

根据这个" Old"文章Is there any sort of "pre login" event or similar?我可以扩展UsernamePasswordFormAuthenticationListener以添加一些代码预登录。

在symfony3中似乎没有security.authentication.listener.form.class参数,那么如何在不更改symfony security_listener.xml配置文件的情况下获得相同的结果?

1 个答案:

答案 0 :(得分:2)

要执行一些登录前/登录后检查(即用户身份验证之前/之后),Symfony框架提供的最简单灵活的解决方案之一是学习How to Create and Enable Custom User Checkers

如果您需要更多控制和灵活性,最好的选择是学习How to Create a Custom Authentication System with Guard。 看一下下面的简单实现示例:

<强> security.yml

    firewall_name:
        guard:
            authenticators:
                - service_name_for_guard_authenticator
            entry_point: service_name_for_guard_authenticator <-- important to add a default one (as described in the docs) if you have many custom authenticators (facebook...)

<强> service.xml中

<service id="service_name_for_guard_authenticator"
         class="AppBundle\ExampleFolderName\YourGuardAuthClassName">
     <argument type="service" id="router"/>        
     <argument type="service" id="security.password_encoder"/>
</service>

<强> YourGuardAuthClassName.php

use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;

class YourGuardAuthClassName extends AbstractGuardAuthenticator
{
    private $router;
    private $passwordEncoder;

    public function __construct(
        Router              $router,
        UserPasswordEncoder $passwordEncoder)
    {
        $this->router          = $router;
        $this->passwordEncoder = $passwordEncoder;
    }

    public function start(Request $request, AuthenticationException $authException = null)
    {
        $response = new RedirectResponse($this->router->generate('your_user_login_route_name'));

        return $response;
    }

    public function getCredentials(Request $request)
    {
        # CHECK IF IT'S THE CHECK LOGIN ROUTE
        if ($request->attributes->get('_route') !== 'your_user_login_route_name'
            || !$request->isMethod('POST')) {
            return null;
        }
        # GRAB ALL REQUEST PARAMETERS
        $params = $request->request->all();
        # SET LOGIN CREDENTIALS
        return array(
            'email'    => $params['email'],
            'password' => $params['password'],
        );
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $email = $credentials['email'];
        $user  = $userProvider->loadUserByUsername($email);
        if (! $user){
            throw new UsernameNotFoundException();
        }

        return $user;
    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        # YOU CAN ADD YOUR CHECKS HERE!
        if (! $this->passwordEncoder->isPasswordValid($user, $credentials['password'])) {
            throw new BadCredentialsException();
        }
        return true;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        # OYU CAN ALSO USE THE EXCEPTIONS TO ADD A FLASH MESSAGE (YOU HAVE TO INJECT YOUR OWN FLASH MESSAGE SERVICE!) 
        if ($exception instanceof UsernameNotFoundException){
            $this->flashMessage->error('user.login.exception.credentials_invalid');
        }
        if ($exception instanceof BadCredentialsException){
            $this->flashMessage->error('user.login.exception.credentials_invalid');
        }

        return new RedirectResponse($this->router->generate('your_user_login_route_name'));
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        return new RedirectResponse($this->router->generate('your_success_login_route_name'));
    }

    public function supportsRememberMe()
    {
        return false;
    }
}