简体   繁体   English

使用remember_me功能登录后,如何刷新/扩展remember_me cookie(到期)?

[英]How do I refresh/extend the remember_me cookie (expiry) after logging in using the remember_me feature?

I'm using Symfony 2.3 LTS. 我正在使用Symfony 2.3 LTS。

I can fully use the remember_me feature in Symfony, including setting it and logging back in after session expiry. 我可以在Symfony中完全使用remember_me功能,包括设置它并在会话到期后重新登录。 However my issue is that once the user is logged back in with the remember_me feature then the expiry isn't refreshed. 但是我的问题是,一旦用户使用remember_me功能重新登录,则不会刷新到期时间。

In other words, if you set the "lifetime" of the remember_me cookie to 14 days then regardless of how many time the user visits the site they will always need to re-authenticate with a full username/password (after 14 days.) I don't want to set a longer cookie as 14 days without visiting seems right. 换句话说,如果您将remember_me cookie的“生命周期”设置为14天,那么无论用户访问该网站的时间长短,他们都需要使用完整的用户名/密码重新进行身份验证(14天后)。不希望设置更长的cookie为14天没有访问似乎是正确的。

I know how to manually set the remember_me cookie. 我知道如何手动设置remember_me cookie。 I just need to know where to put that code. 我只需要知道放置代码的位置。

I've tried these: 我试过这些:

  1. This SO question doesn't do what I want and is very different. 这个问题不符合我的要求而且非常不同。

  2. There doesn't appear to be any settings in the security.yml configuration (to refresh expiry.) security.yml配置中似乎没有任何设置(刷新到期时间。)

  3. Hooking in on the processAutoLoginCookie method in Symfony\\Component\\Security\\Http\\RememberMe\\TokenBasedRememberMeServices , but that can't work as there's no access to a Response (to set the cookie manually.) Symfony\\Component\\Security\\Http\\RememberMe\\TokenBasedRememberMeServices挂钩processAutoLoginCookie方法,但由于无法访问Response(手动设置cookie),因此无法工作。

  4. Listening on the SecurityEvents::INTERACTIVE_LOGIN event looks a good idea, but InteractiveLoginEvent doesn't have access to the Response either. 监听SecurityEvents::INTERACTIVE_LOGIN事件看起来不错,但InteractiveLoginEvent也无法访问Response。 Here's an example. 这是一个例子。

  5. I could get messy by setting a request attribute using one of the above and then setting a response listener to detect for that, but I think that's too messy. 我可以通过使用上面的一个设置一个请求属性,然后设置一个响应监听器来检测它,但我认为这太乱了。 There must be a better way to do it. 必须有更好的方法来做到这一点。

  6. I could use one of the above to listen on the request, generate a response (eg redirect), set the cookie, perform the redirect, but again that's not good enough. 我可以使用上面的一个来监听请求,生成一个响应(例如重定向),设置cookie,执行重定向,但这又不够好。

My proposed approach: 我建议的方法:

  1. Set up a kernel.response listener 设置kernel.response监听器
  2. Pass the SecurityContext to the listener constructor SecurityContext传递给侦听器构造函数
  3. Detect a logged in user 检测登录用户
  4. Manually set your remember_me cookie 手动设置remember_me cookie
  5. Set a session var to prevent future cookie sets 设置会话var以防止将来的cookie集
  6. Your new cookie will piggyback on the next page a user loads when logged in using the remember_me cookie. 当您使用remember_me cookie登录时,您的新cookie将搭载用户加载的下一页。

services.yml services.yml

services:
    acme.response_listener:
        class: AcmeBundle\EventListener\ResponseListener
        arguments: ['@security.context']
        tags:
            - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }

ResponseListener ResponseListener

namespace AcmeBundle\EventListener;

use Symfony\Component\Security\Http\Event\FilterResponseEvent;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Cookie;

class ResponseListener
{
    /** @var \Symfony\Component\Security\Core\SecurityContext */
    private $securityContext;

    /**
     * Constructor
     * 
     * @param SecurityContext $securityContext
     */
    public function __construct(SecurityContext $securityContext)
    {
        $this->securityContext = $securityContext;
    }

    public function onKernelResponse(FilterResponseEvent $event)
    {
        $session = $event->getRequest()->getSession();
        if (
            $this->securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED') // remember_me cookie used
            && !$session->get('cookie_extended') // cookie hasn't been extended
        ) {
            $response = $event->getResponse(); // get the Response object
            $cookie = new Cookie(...); // your cookie
            $response->headers->setCookie($cookie); // set that cookie!
            $session->set('cookie_extended', true); // prevent future cookie sets for the current session
        }
    }
}

I haven't tested this code but it should be enough theory to get you started in this direction. 我没有测试过这段代码,但它应该足以让你开始朝这个方向发展。

The expiry timestamp and the password are both part of the hash of the cookie value, so it seems that the rememberme cookie can only be set at login since the password must be available to extend the timestamp. 到期时间戳和密码都是cookie值的哈希值的一部分,因此似乎只能在登录时设置rememberme cookie,因为密码必须可用于扩展时间戳。

From https://stackoverflow.com/a/9069098 : 来自https://stackoverflow.com/a/9069098

If you are setting the rememberme cookie directly, you have to use the following format: 如果要直接设置记忆cookie,则必须使用以下格式:

 base64_encode(<classname>:base64_encode(<username>):<expiry-timestamp>:<hash>) 

where the hash will be: 哈希将在哪里:

 sha256(<classname> . <username> . <expiry-timestamp> . <password> . <key>) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM