创建一个symfony2手动记住我的cookie(FOSUserBundle)

Jon*_*ers 8 remember-me symfony fosuserbundle

有人可以解释一下如何在控制器中手动创建记住我的cookie吗?

我希望用户在按下"注册"按钮后保持登录状态,而不必在之后使用他们的凭据登录.

我试图手动创建一个cookie,但我猜测cookie值是不正确的,因此"记住我"功能不起作用.设置具有正确名称的cookie.我检查过了.

当使用具有用户凭据的正常登录过程时,记住我的功能按预期工作.

security.yml security.yml记得我

security:
   firewalls:
       main:
           remember_me:
               lifetime: 86400
               domain:   ~
               path:     /
               key:      myKey
Run Code Online (Sandbox Code Playgroud)

这就是我现在所拥有的,即使设置了cookie,它也不起作用.

$um = $this->get('fos_user.user_manager');
$member = $um->createUser();

… Form stuff with bindRequest etc.

$um->updatePassword($member);
$um->updateUser($member);

$providerKey = $this->container->getParameter('fos_user.firewall_name');
$securityKey = 'myKey';

$token = new RememberMeToken($member, $providerKey, $securityKey,
$member->getRoles());
$this->container->get('security.context')->setToken($token);

$redirectResponse = new RedirectResponse($url);
$redirectResponse->headers->setCookie(
   new \Symfony\Component\HttpFoundation\Cookie(
       'REMEMBERME',
       base64_encode(implode(':', array($member->getUsername(),
$member->getPassword()))),
       time() + 60*60*24
   )
);
return $redirectResponse;
Run Code Online (Sandbox Code Playgroud)

更新:

我也尝试使用反射处理PersistentTokenBasedRememberMeServices类,但它不起作用.一个cookie被设置但它不起作用

$token = $this->container->get('security.context')->getToken();

$providerKey = $this->container->getParameter('fos_user.firewall_name');
$securityKey = 'myKey';

$persistenService = new
PersistentTokenBasedRememberMeServices(array($um), $providerKey,
$securityKey, array('path' => '/', 'name' => 'REMEMBERME', 'domain' =>
null, 'secure' => false, 'httponly' => true,
'lifetime' => 86400));
$persistenService->setTokenProvider(new InMemoryTokenProvider());

$method = new \ReflectionMethod('Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices',
'onLoginSuccess');
 $method->setAccessible(true);
$method->invoke($persistenService, $request, $redirectResponse, $token);
Run Code Online (Sandbox Code Playgroud)

我正在使用Symfony v2.0.5和FOSUserBundle 1.0

更新2:

我尝试了第三种方式.与上述相同但没有反思:

$token = $this->container->get('security.context')->getToken();

$providerKey = $this->container->getParameter('fos_user.firewall_name');
$securityKey = 'myKey';

$persistenService = new PersistentTokenBasedRememberMeServices(array($um), $providerKey, $securityKey, array('path' => '/', 'name' => 'REMEMBERME', 'domain' => null, 'secure' => false, 'httponly' => true, 'lifetime' => 31536000, 'always_remember_me' => true, 'remember_me_parameter' => '_remember_me'));
$persistenService->setTokenProvider(new InMemoryTokenProvider());

$persistenService->loginSuccess($request, $redirectResponse, $token);
Run Code Online (Sandbox Code Playgroud)

grz*_*hoo 13

我就是这样做的.我没有使用FOSUserBundle而且我正在使用Doctrine Entity User Provider,但是根据您的需求调整它应该是微不足道的.这是一般解决方案:

// after registration and persisting the user object to DB, I'm logging the user in automatically
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());

// but you can also get the token directly, if you're user is already logged in
$token = $this->container->get('security.context')->getToken();

// write cookie for persistent session storing
$providerKey = 'main'; // defined in security.yml
$securityKey = 'MySecret'; // defined in security.yml

$userProvider = new EntityUserProvider($this->getDoctrine()->getEntityManager(), 'MyCompany\MyBundle\Entity\User', 'username');

$rememberMeService = new TokenBasedRememberMeServices(array($userProvider), $securityKey, $providerKey, array(
                'path' => '/',
                'name' => 'MyRememberMeCookie',
                'domain' => null,
                'secure' => false,
                'httponly' => true,
                'lifetime' => 1209600, // 14 days
                'always_remember_me' => true,
                'remember_me_parameter' => '_remember_me')
            );

$response = new Response();
$rememberMeService->loginSuccess($request, $response, $token);

// further modify the response
// ........

return $response;
Run Code Online (Sandbox Code Playgroud)

只要记住你必须设置always_remember_me optiontrue(像我一样在上面的代码中),或者有它在你的$ _ POST参数不知何故,否则方法isRememberMeRequestedAbstractRememberMeServices返回false和cookie将不会被保存.

你非常接近正确的解决方案:)你做错了(在第3次尝试中)是你在这里改变了参数的顺序:

$persistenService = new PersistentTokenBasedRememberMeServices(array($um), $providerKey, $securityKey, array('path' => '/', 'name' => 'REMEMBERME', 'domain' => null, 'secure' => false, 'httponly' => true, 'lifetime' => 31536000, 'always_remember_me' => true, 'remember_me_parameter' => '_remember_me'));
Run Code Online (Sandbox Code Playgroud)

看看__construct()AbstractRememberMeServices.php.你应该传递一个$securityKey作为第二个参数和$providerKey第三个参数,而不是像你错误的那样传递;)

我还不知道的是,如何直接在控制器中从security.yml获取参数,而不是复制它.通过使用$this->container->getParameter()我可以获取存储parameters在config.yml中的键下的参数,但不能将配置树中的参数放在更高的位置.有什么想法吗?

  • +1为此使用Symfony2安全类.请记住,remember-me cookies的默认cookie名称是"REMEMBERME".只有当您使用与防火墙相同的cookie名称时,才会通过安全监听器识别您的手动设置cookie进行身份验证. (3认同)

Jay*_*aph 10

如果要直接设置记忆cookie,则必须使用以下格式:

base64_encode(<classname>:base64_encode(<username>):<expiry-timestamp>:<hash>)
Run Code Online (Sandbox Code Playgroud)

哈希将在哪里:

sha256(<classname> . <username> . <expiry-timestamp> . <password> . <key>)
Run Code Online (Sandbox Code Playgroud)

密钥是您在安全性(.xml/.yml)中输入的密钥remember_me.

这取自文件中的processAutoLoginCookie()方法Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeService.php.

这都是由generateCookieValue()同一类中的方法完成的.

但是,我不建议直接使用这种方式,但尝试看看是否可以调用该TokenBasedRememberMeService::onLoginSuccess()方法,为您设置此cookie以使代码更健壮和可移植.