7

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'));

最初のページ(リダイレクトなし):

最初のページ-ログイン

2ページ目:

2ページ目-もうログインしていません

4

1 に答える 1

6

カスタムログインには、次のコードのみが必要です。

$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;
    }
}
于 2013-01-15T14:26:31.210 に答える