-->

登录程序并保持登录状态(Login programmatically and stay logged

2019-08-06 19:25发布

我试图在访问使用Symfony2的网站实现单点登录。

认证本身似乎很好地工作,但仅限于初始页面。 在加载的用户的下一个页面是不是在登录了。

相关的代码:

$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$event = new InteractiveLoginEvent($request, $token);

$this->get("event_dispatcher")->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $event);
$this->get("security.context")->setToken($token);

return $this->redirect($this->generateUrl('sonata_user_profile_show'));

第一页(无需重定向):

第二页:

Answer 1:

只有下面的代码是必要的自定义日志项。

$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get("security.context")->setToken($token);

return $this->redirect($this->generateUrl('sonata_user_profile_show'));

这样做是在安全上下文设置UsernamePasswordToken。 此令牌(以及用户)将被序列化,并把会话。 在接下来的页面中的令牌将从会议中被去系列化和,还去系列化,用户将被刷新。

该用户的运营商在FOSUserBundle不使用序列化的用户的ID这个令人耳目一新。

此外,Doctrine2在某些情况下,使用代理类为实体类,而不是原来的实体类。 该代理类通过一个复杂的延迟加载复杂的执行将覆盖实体“的getId()”函数。

这一起可能导致的是,当你把Doctrine2代理对象的序列化和反序列化,然后代理对象的UserPasswordToken的“的getId()”将不会返回原来的ID的事实。 当发生这种情况的用户不能由用户的运营商被刷新,并且令牌将失效。

一种用于此修复创建自定义用户的运营商,通过使用用户名(或其它的唯一属性)清凉覆盖“refreshUser()”。

//...
class UserProvider extends FOSUserProvider
{
    /**
     * {@inheritDoc}
     */
    public function refreshUser(SecurityUserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('Expected an instance of User, but got "%s".', get_class($user)));
        }

        if (null === $reloadedUser = $this->userManager->findUserBy(array('username' => $user->getUsername()))) {
            throw new UsernameNotFoundException(sprintf('User with username "%s" could not be reloaded.', $user->getUsername()));
        }

        return $reloadedUser;
    }
}


文章来源: Login programmatically and stay logged in