首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >symfony 4:在成功的身份验证之后,它重定向到管理区域,并使用匿名令牌填充TokenStorage

symfony 4:在成功的身份验证之后,它重定向到管理区域,并使用匿名令牌填充TokenStorage
EN

Stack Overflow用户
提问于 2020-08-17 15:43:54
回答 2查看 573关注 0票数 0

我有一个旧的Symfony 3.1站点,我把它升级到Symfony 3.4.x,然后升级到Symfony 4.4.11,但是我没有将它升级到symfony flex。我修了很多东西,公共网站看起来也很管用。

我不得不重新构建身份验证,因为旧的身份验证与sf4不兼容。

我跟踪了这个https://symfony.com/doc/4.4/security/form_login_setup.html

这个:https://symfonycasts.com/screencast/symfony-security/make-user

最后,在成功的身份验证之后,当它重定向到管理区域时,它总是再次检查LoginFormAuthenticator,这显然不支持管理区域,并且它与匿名用户一起重定向回登录页面。

有许多关于这个问题的讨论,并尝试了我发现的所有东西,但我没有找到解决办法。即使调试它也不行。

保存在定义路径中的会话。它的id与浏览器中的PHPSESSID相同。站点运行HTTP协议。

security.yml

代码语言:javascript
运行
复制
security:
    encoders:
        AppBundle\Entity\User:
            algorithm: bcrypt
            cost: 12

    providers:
        user_provider:
            entity:
                class: AppBundle:User
                property: email

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt|error)|css|images|js)/
            security: false

        main:
            stateless: true
            pattern: ^/
            anonymous: true
            logout_on_user_change: true

            guard:
                authenticators:
                    - AppBundle\Security\LoginFormAuthenticator

            form_login:
                provider: user_provider
                username_parameter: email
                csrf_token_generator: security.csrf.token_manager
                login_path: app_login

            logout:
                path: app_logout


    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }
        - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

路由:

代码语言:javascript
运行
复制
app_login:
    path:     /login
    defaults: { _controller: AppBundle\Controller\BackendController:loginAction }

app_logout:
    path:     /logout
    defaults: { _controller: AppBundle\Controller\BackendController:logoutAction }

app_admin:
    path:         /admin/{page}/{entry}
    defaults:     { _controller: AppBundle\Controller\BackendController:showAction, entry: null }

User.php

代码语言:javascript
运行
复制
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User implements UserInterface, \Serializable, EquatableInterface
{
    private $id;
    // and so on

    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->email,
            $this->password
        ));
    }

    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->email,
            $this->password,
        ) = unserialize($serialized);
    }

    public function getRoles()
    {
        return array('ROLE_ADMIN');
    }

    public function getUsername()
    {
        return $this->getEmail();
    }

    public function isEqualTo(UserInterface $user)
    {
        if (!$user instanceof User) {
            return false;
        }

        if ($this->password !== $user->getPassword()) {
            return false;
        }

        if ($this->salt !== $user->getSalt()) {
            return false;
        }

        if ($this->email !== $user->getUsername()) {
            return false;
        }

        return true;
    }

}

后端控制器:

代码语言:javascript
运行
复制
class BackendController extends AbstractController
{
    public function loginAction(AuthenticationUtils $authenticationUtils)
    {
        return $this->render('AppBundle:Backend:page.html.twig', array(
            'email' => $authenticationUtils->getLastUsername(),
            'error' => $authenticationUtils->getLastAuthenticationError()
        ));
    }

    public function logoutAction()
    {
        $this->container->get('security.token_storage')->setToken(null);
        $this->container->get('request')->getSession()->invalidate();
    }

    public function showAction(Request $request, $page, $entry)
    {
        $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

        // some logic
    }
}

LoginFormAuthentication.php

在这个例子中看起来是一样的,而且它是有效的。它成功地到达onAuthenticationSuccess()并重定向到管理区域。

dev.log

代码语言:javascript
运行
复制
request.INFO: Matched route "app_login". {"route":"app_login"..}
security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"main","authenticators":1} []
security.DEBUG: Checking support on guard authenticator. {"firewall_key":"main","authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []
security.DEBUG: Calling getCredentials() on guard authenticator. {"firewall_key":"main","authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []
security.DEBUG: Passing guard token information to the GuardAuthenticationProvider {"firewall_key":"main","authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []
doctrine.DEBUG: SELECT t0.* FROM user t0 WHERE t0.email = ? LIMIT 1 ["email@me.com"] []
security.INFO: Guard authentication successful! {"token":"[object] (Symfony\\Component\\Security\\Guard\\Token\\PostAuthenticationGuardToken: PostAuthenticationGuardToken(user=\"email@me.com\", authenticated=true, roles=\"ROLE_ADMIN\"))","authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []
security.DEBUG: Guard authenticator set success response. Redirect response
security.DEBUG: Remember me skipped: it is not configured for the firewall.
security.DEBUG: The "AppBundle\Security\LoginFormAuthenticator" authenticator set the response. Any later authenticator will not be called {"authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []

重定向后:

代码语言:javascript
运行
复制
request.INFO: Matched route "app_admin". {"route":"app_admin" ..}
security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"main","authenticators":1} []
security.DEBUG: Checking support on guard authenticator. {"firewall_key":"main","authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []
security.DEBUG: Guard authenticator does not support the request. {"firewall_key":"main","authenticator":"AppBundle\\Security\\LoginFormAuthenticator"} []
security.INFO: Populated the TokenStorage with an anonymous Token. [] []
security.DEBUG: Access denied, the user is not fully authenticated; redirecting to authentication entry point.
security.DEBUG: Calling Authentication entry point. [] []
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-17 18:21:23

我的同事搞清楚了问题出在哪里。实际上,上面的代码有多个问题。

使用https://github.com/symfony/symfony/blob/4.4/UPGRADE-4.0.md#security

  • logout_on_user_change整数的
  1. 已从sf4中删除:
  2. 是不必要的,在防火墙中不需要GuardAuthenticator true是一个错误设置,但当我删除它时,它会抛出一个先前的错误:“由于用户更改了令牌,所以无法刷新令牌。令牌在试图刷新令牌后被取消身份验证。”这是因为
  3. in isEqualTo,我检查了$this->salt !== $user->getSalt(),但没有序列化

,所以工作解决方案看起来像这个

same

  • LoginFormAuthentication.php
  • 路由是相同的
  • ,后端控制器是被删除的

security.yml

代码语言:javascript
运行
复制
security:
    encoders:
        AppBundle\Entity\User:
            algorithm: bcrypt
            cost: 12

    providers:
        user_provider:
            entity:
                class: AppBundle:User
                property: email

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt|error)|css|images|js)/
            security: false

        main:
            anonymous: ~
            provider: user_provider

            form_login:
                login_path: app_login
                check_path: app_login
                default_target_path: app_admin

            logout:
                path: app_logout

    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }
        - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

User.php

代码语言:javascript
运行
复制
class User implements UserInterface, \Serializable, EquatableInterface
{

    // ..

    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->email,
            $this->password,
            $this->salt,
        ));
    }

    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->email,
            $this->password,
            $this->salt
            ) = unserialize($serialized, array('allowed_classes' => false));
    }

    public function isEqualTo(UserInterface $user)
    {
        if (!$user instanceof User) {
            return false;
        }

        if ($user->getId() == $this->getId()) {
            return true;
        }

        if ($this->password !== $user->getPassword()) {
            return false;
        }

        if ($this->salt !== $user->getSalt()) {
            return false;
        }

        if ($this->email !== $user->getUsername()) {
            return false;
        }

        return true;
    }
}
票数 0
EN

Stack Overflow用户

发布于 2020-08-17 17:11:32

必须更改保护身份验证器AppBundle\Security\LoginFormAuthenticator

这向守卫解释,您只需要检查登录页面上的凭据。

代码语言:javascript
运行
复制
public function supports(Request $request)
{
    return 'login_route' === $request->attributes->get('_route') && $request->isMethod('POST');
}

https://symfony.com/doc/4.4/security/guard_authentication.html#avoid-authenticating-the-browser-on-every-request

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63454223

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档