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

手动创建symfony2记住我cookie(FOSUserBundle),symfony,remember-me,fosuserbundle,Symfony,Remember Me,Fosuserbundle,有人能解释一下如何在控制器中手动创建“记住我”cookie吗 我希望用户在按下“注册表”后保持登录状态 按钮,而无需随后使用其凭据登录 我试图手动创建cookie,但我猜是cookie 值不正确,因此“记住我”功能 不起作用。 将设置具有正确名称的cookie。我查过了 当使用普通模式时,“记住我”功能按预期工作 使用用户凭据的登录过程 security.yml 我记得我 security: firewalls: main: remember_me:

有人能解释一下如何在控制器中手动创建“记住我”cookie吗

我希望用户在按下“注册表”后保持登录状态 按钮,而无需随后使用其凭据登录

我试图手动创建cookie,但我猜是cookie 值不正确,因此“记住我”功能 不起作用。 将设置具有正确名称的cookie。我查过了

当使用普通模式时,“记住我”功能按预期工作 使用用户凭据的登录过程

security.yml 我记得我

security:
   firewalls:
       main:
           remember_me:
               lifetime: 86400
               domain:   ~
               path:     /
               key:      myKey
这就是我现在拥有的,即使设置了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;
更新:

我也试着和 PersistentTokenBasedMemberMeservices类具有反射,但它不起作用。一块饼干被设置好了,但它不起作用

$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);
我使用的是symfonyv2.0.5和fosuserbundle1.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);

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

base64_encode(<classname>:base64_encode(<username>):<expiry-timestamp>:<hash>)
base64\u编码(:base64\u encode():)
其中散列将是:

sha256(<classname> . <username> . <expiry-timestamp> . <password> . <key>)
sha256(…)
密钥是您在
记住我
部分的安全(.xml/.yml)中输入的密钥

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

这都是通过同一类中的
generateCookieValue()
方法完成的


但是,我不建议直接使用这种方法,但请尝试调用
TokenBasedMemberMeservice::onLoginSAccess()
方法,该方法为您设置此cookie,以使代码更加健壮和可移植。

我是这样做的。我没有使用FOSUserBundle,我使用的是Doctrine实体用户提供者,但根据您的需要进行调整应该是微不足道的。以下是一个通用解决方案:

// 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;
请记住,您必须将
始终记住我选项
设置为
true
(就像我在上面的代码中所做的那样),或者以某种方式将其设置在$\u POST参数中,否则
AbstractMemberServices
的方法
IsRememberRequested
将返回false,并且cookie将不会被存储

不过,您已经非常接近正确的解决方案:)您(在第三次尝试中)的错误在于更改了此处参数的顺序:

$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'));
查看
AbstractMemberServices.php
中的
\uu construct()
。您应该将
$securityKey
作为第二个参数传递,将
$providerKey
作为第三个参数传递,而不是错误地传递;)


我还不知道的是,如何在控制器中直接从security.yml获取参数,以避免重复。通过使用
$this->container->getParameter()
我可以获取存储在config.yml中
参数
键下的参数,但不能获取配置树中较高位置的参数。对此有何想法?

对我来说,最简单的解决方案是扩展BaseTokedRememberMeservices并让它处理

namespace AppBundke\Security\Http;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices as BaseTokenBasedRememberMeServices;


class TokenBasedRememberMeServices extends BaseTokenBasedRememberMeServices
{
     protected $options_new = array('name' => 'REMEMBERME', 'domain' => null, 'path' => '/');

     public function __construct($userProvider, $secret, $providerKey, array $options = array(), LoggerInterface $logger = null)
     {
          return parent::__construct(array($userProvider), $secret, $providerKey, array_merge($this->options_new, $options));
     }

     public function generateCookie($user, $username, $expires, $password)
     {
        $cookie = new Cookie(
             $this->options['name'],
             parent::generateCookieValue(get_class($user), $username, $expires, $password),
             $expires,
             $this->options['path'],
             $this->options['domain'],
             $this->options['secure'],
             $this->options['httponly']
        );
    return $cookie;
    }
}
以及在控制器中

$user = $this->getUser();
$providerKey = $this->getParameter('fos_user.firewall_name');
$secret = $this->getParameter('secret');
$cookie_life_time = $this->getParameter('cookie_life_time');

$remember_me_service = new TokenBasedRememberMeServices($user, $secret, $providerKey );
$remember_me_cookie = $remember_me_service->generateCookie($user, $user->getUsername(),(time() + $cookie_life_time), $user->getPassword());
然后,响应将cookie设置为$membere\u me\u cookie


我希望它能与您一起工作。2.

当我尝试在通过令牌连接后使用设置REMEMBERME cookie给用户时,我遇到了相同的问题

在这种情况下,我没有响应对象可以使用$Response->headers->setCookie(),需要使用()。 在这种情况下,创建重定向响应是不合适的

这需要重构,但我发布了我基于服务的原始过程

$expires = time() + 2628000;
$hash = hash_hmac(
    'sha256',
     get_class($user).$user->getUsername().$expires.$user->getPassword(), 'secret in parameters.yml'
);
$value = base64_encode(implode(':', [get_class($user), base64_encode($user->getUsername()), $expires, $hash]));
setcookie(
    'REMEMBERME',
    $value,
    $expires,
    '/',
    'host',
    'ssl boolean',
    true
);

为了在security.yml中获取cookie参数并避免重复,您应该将它们放在parameters.yml和security.yml中,并使用%your_parameter_name%调用它们。它们现在可以在security和parameters+1中使用,以便为此使用Symfony2安全类。请记住,“记住我”cookies的默认cookie名称是
REMEMBERME
。仅当您使用与防火墙相同的cookie名称时,安全侦听器才会识别针对手动设置cookie进行身份验证的防火墙。传递给Symfony\Bridge\doctor\security\User\EntityUserProvider的参数1::\uu construct()必须实现接口doctor\Common\Persistence\manager注册表,Doctrine\ORM\EntityManager的实例,我只发送了Doctrine而没有EntityManager,修复了D:问题。所以基本上只需$this->getDoctrine(),谢谢:)现在我需要确保它工作正常。