Symfony 4-未设置Custom GuardAuthenticator记住我的cookie

时间:2019-02-24 15:23:27

标签: symfony symfony4

我正在构建一个自定义GuardAuthenticator,以使用特定路径上的令牌登录。根据{{​​3}},如果supportsRememberMe()返回trueremember_me在防火墙中被激活,则应该设置“记住我” cookie,但不设置(尽管如果我设置了,在另一条路线上使用表单登录身份验证)。

路线:

/**
 * @Route("/login/token/{id}/{token}/{force}", defaults={"force"=0}, name="login_token")
 */
public function loginToken()
{

}

GuardAuthenticator:

<?php


namespace App\Security;


use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;

class TokenLoginAuthenticator extends AbstractGuardAuthenticator
{
    use TargetPathTrait;

    private $em;
    private $force;

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

    public function supports(Request $request)
    {
        return 'login_token' === $request->attributes->get('_route') && $request->isMethod('GET');
    }


    public function getCredentials(Request $request)
    {
        $credentials = [
            'id' => $request->attributes->get('id'),
            'token' => $request->attributes->get('token')
        ];

        $this->force = $request->attributes->get('force');

        return $credentials;
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $user = $this->em->getRepository(User::class)->find($credentials['id']);

        if (!$user) {
            // fail authentication with a custom error
            throw new CustomUserMessageAuthenticationException('No user found.');
        }

        return $user;
    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        if ($user->getToken() === $credentials['token']) {
            return true;
        }
        throw new HttpException(403, "Forbidden");
    }


    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
            return new RedirectResponse($targetPath);
        }
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        throw new HttpException(403, "Forbidden");
    }

    public function start(Request $request, AuthenticationException $authException = null)
    {
    }

    public function supportsRememberMe()
    {
        return true;
    }
}

安全配置:

security:
    encoders:
        App\Entity\User:
            id: 'App\Security\PasswordEncoder'

    providers:
        in_memory: { memory: ~ }
        orm:
            entity:
                class: App\Entity\User
                property: email

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            anonymous: true
            form_login:
                login_path: login
                check_path: login
                provider: orm
                csrf_token_generator: security.csrf.token_manager
                default_target_path: homepage

            logout:
                path:   /logout
                target: /

            remember_me:
                secret:   '%kernel.secret%'
                lifetime: 604800 # 1 week in seconds
                path: /
                # by default, the feature is enablered by checking a
                # checkbox in the login form (see below), uncomment the
                # following line to always enable it.
                # always_remember_me: true

            guard:
                provider: orm
                authenticators:
                    - App\Security\TokenLoginAuthenticator

2 个答案:

答案 0 :(得分:0)

如果满足以下所有的条件,则会设置

记住我的cookie:

  • if (browserOk) { platformBrowserDynamic().bootstrapModule(AppModule); } else { // browser unsupported } 方法返回supportsRememberMe()
  • 已配置防火墙中的true键。
  • (默认)remember_me参数在请求中发送。通常可以通过在登录表单中具有一个_remember_me复选框来完成此操作(但可以将其作为url参数(_remember_me发送),也可以将防火墙?_remember_me=1密钥配置为{{1 }}。
  • remember_me方法返回一个Response对象。

答案 1 :(得分:0)

在 Symfony 5.2.6 中不要忘记添加新的 RememberMeBadge() 到身份验证函数:

use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;

class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
    public function authenticate(Request $request): PassportInterface
    {
        $email = $request->request->get('email', '');

        $request->getSession()->set(Security::LAST_USERNAME, $email);

        return new Passport(
            new UserBadge($email),
            new PasswordCredentials($request->request->get('password', '')),
            [
                new CsrfTokenBadge('authenticate', $request->get('_csrf_token')),
                new RememberMeBadge(),
            ]
        );
    }
}