You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 6.4中SuperUser登录跳转后丢失用户问题排查

Symfony 6.4 SuperUser登录后状态丢失问题

在Symfony 6.4应用中为新实体SuperUser实现登录功能,严格遵循官方文档操作,登录验证成功,但跳转至其他页面或访问新页面后,登录用户状态丢失。

已排查方向:

  • 测试会话可正常存储数据,调整会话配置无效;
  • 尝试自定义Authenticator未解决问题;
  • 日志和调试工具无有效报错提示;
  • 已简化security.yaml配置,怀疑FOSUserBundle或FOSOAuthServerBundle存在干扰,但未定位具体原因。

日志信息

[2024-09-16T17:27:20.694109+02:00] security.INFO: Authenticator successful! {"token":{"Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken":"UsernamePasswordToken(user=\"tomatom\", roles=\"ROLE_SUPER_ADMIN, ROLE_USER\")"},"authenticator":"Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator"} []
[2024-09-16T17:27:20.696821+02:00] app.DEBUG: Notified event "security.interactive_login" to listener "FOS\UserBundle\EventListener\LastLoginListener::onSecurityInteractiveLogin". {"event":"security.interactive_login","listener":"FOS\UserBundle\EventListener\LastLoginListener::onSecurityInteractiveLogin"} []
[2024-09-16T17:27:20.926611+02:00] app.DEBUG: Notified event "Symfony\Component\Security\Http\Event\LoginSuccessEvent" to listener "Symfony\Component\Security\Http\EventListener\SessionStrategyListener::onSuccessfulLogin". {"event":"Symfony\Component\Security\Http\Event\LoginSuccessEvent","listener":"Symfony\Component\Security\Http\EventListener\SessionStrategyListener::onSuccessfulLogin"} []
[2024-09-16T17:27:20.926800+02:00] app.DEBUG: Notified event "Symfony\Component\Security\Http\Event\LoginSuccessEvent" to listener "Symfony\Component\Security\Http\EventListener\PasswordMigratingListener::onLoginSuccess". {"event":"Symfony\Component\Security\Http\Event\LoginSuccessEvent","listener":"Symfony\Component\Security\Http\EventListener\PasswordMigratingListener::onLoginSuccess"} []
[2024-09-16T17:27:20.926905+02:00] security.DEBUG: The "Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator" authenticator set the response. Any later authenticator will not be called {"authenticator":"Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator"} []
[2024-09-16T17:27:21.044256+02:00] doctrine.INFO: Disconnecting [] []
[2024-09-16T17:27:21.146985+02:00] request.INFO: Matched route "admin_company_list". {"route":"admin_company_list","route_parameters":{"_route":"admin_company_list","_controller":"App\Controller\CompanyController::index"},"request_uri":"http://127.0.0.5/admin/company/list","method":"GET"} []
[2024-09-16T17:27:21.364243+02:00] security.DEBUG: Checking for authenticator support. {"firewall_name":"admin","authenticators":1} []
[2024-09-16T17:27:21.364393+02:00] security.DEBUG: Checking support on authenticator. {"firewall_name":"admin","authenticator":"Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator"} []
[2024-09-16T17:27:21.364464+02:00] security.DEBUG: Authenticator does not support the request. {"firewall_name":"admin","authenticator":"Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator"} []
[2024-09-16T17:27:21.416471+02:00] security.DEBUG: Access denied, the user is not fully authenticated; redirecting to authentication entry point. {"exception":"[object] (Symfony\Component\Security\Core\Exception\AccessDeniedException(code: 403): Access Denied. at /var/www/vendor/symfony/security-http/Firewall/AccessListener.php:87)"} []

简化后的security.yaml配置

security:
  password_hashers:
    App\Entity\SuperUser: 'auto'

  providers:
    super_user_provider:
      entity:
        class: App\Entity\SuperUser
        property: username

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

    admin:
      pattern: ^/admin
      provider: super_user_provider
      stateless: false
      form_login:
        login_path: admin_login
        check_path: admin_login
        enable_csrf: false
        default_target_path: admin_company_list
      logout:
        path: admin_logout

  role_hierarchy:
      ROLE_SUPER_ADMIN: ~
      ROLE_ORDER_SELLITEMS: ~
      ROLE_SALESMAN: ~
      ROLE_SERVER_ADMIN:
          - ROLE_ORDER_SHOW
      ROLE_PICKING_REQUIRED_NOTE: ~
      ROLE_ORDER_GROUP_ONLY_MY: ~
      ROLE_CUSTOMER_ONLY_MY: ~

  access_control:
    - { path: '^/admin/login/[a-z]{2}', roles: [ PUBLIC_ACCESS ] }
    - { path: ^/admin, roles: [ ROLE_SERVER_ADMIN, IS_AUTHENTICATED_FULLY ] }

FOS相关配置

fos_oauth_server.yaml

fos_oauth_server:
    db_driver: orm
    client_class:        App\Entity\OAuth\Client
    access_token_class:  App\Entity\OAuth\AccessToken
    refresh_token_class: App\Entity\OAuth\RefreshToken
    auth_code_class:     App\Entity\OAuth\AuthCode
    service:
        user_provider: fos_user.user_provider.username_email
        options:
            supported_scopes: user
            access_token_lifetime: 43200
            refresh_token_lifetime: 1209600

services:
    fos_oauth_server.client_manager:
        class: App\Util\ClientManager
        arguments:
            - '@App\Repository\ClientRepository'

fos_user.yaml

fos_user:
    from_email:
        address: '%env(resolve:SENDER_EMAIL_ADDRESS)%'
        sender_name: '%env(resolve:SENDER_EMAIL_NAME)%'
    db_driver: orm
    firewall_name: fos_user
    user_class: App\Entity\User
    service:
        mailer: App\Service\FosMailer

NelmioCorsBundle配置

nelmio_cors:
    defaults:
        allow_credentials: false
        allow_origin: []
        allow_headers: []
        allow_methods: []
        expose_headers: []
        max_age: 0
        hosts: []
        origin_regex: false
    paths:
        '^/':
            origin_regex: true
            allow_origin: ['^http://localhost:[0-9]+']
            allow_headers: ['*']
            allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
            max_age: 3600
            hosts: ['^api\.']

相关业务代码

SuperUser.php

#[ORM\Table(name: 'super_user')]
#[ORM\Entity(repositoryClass: SuperUserRepository::class)]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])]
class SuperUser implements UserInterface, PasswordAuthenticatedUserInterface
{
...
}

LoginController.php

#[Route('/admin/login/{_locale}', name: 'admin_login')]
public function login(AuthenticationUtils $authenticationUtils): Response
{
    $error = $authenticationUtils->getLastAuthenticationError();
    $lastUsername = $authenticationUtils->getLastUsername();

    return $this->render('login/index.html.twig', [
        'last_username' => $lastUsername,
        'error' => $error,
    ]);
}

登录表单

<form action="{{ path('admin_login') }}" method="post">
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
    <label for="username">Jméno:</label>
    <input type="text" id="username" name="_username" class="form-control my-1"
           value="{{ last_username }}" required>

    <label for="password">Heslo:</label>
    <input type="password" id="password" name="_password" class="form-control my-1" required>

    <input type="hidden" name="_target_path" value="{{ path('admin_company_list') }}">

    <button type="submit" class="btn btn-primary float-end my-2">Přihlásit</button>
</form>

内容的提问来源于stack exchange,提问作者Matys333

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:22:04