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

Symfony 5+生产环境自定义查询登录功能异常求助

Symfony 5.x/6.x生产环境登录异常:非ID=0域用户无法保持登录状态

问题概述

开发一款采用user@domain形式登录的vmail应用,包含Domain实体及关联的User实体。原Symfony 3.x版本在开发/生产环境均正常;升级至Symfony 5.x/6.x后,开发环境正常,但生产环境出现可复现异常:

  • 域ID=0的用户登录正常,域ID≠0的用户登录后会被重定向回登录页,无错误提示;
  • 手动输入目标URL仍会被重定向,首页打印$this->getUser()在生产环境返回null,但仓库查询可获取到对应用户记录;
  • 输入错误密码时正常显示错误提示;
  • 仅APP_ENV=prod时触发问题,dev环境无异常,已在3台Debian服务器、Apache/Nginx环境下复现。

复现步骤

  • 克隆项目的symfony62分支(默认分支为Symfony3.x版本)
  • 完成项目安装流程
  • 创建新域及该域下的用户
  • 使用该用户尝试登录,观察重定向问题

相关配置与代码

security.yaml配置

security:
    password_hashers:
      App\Entity\User:
        id: App\Utils\PassEncoder
    providers:
        app_vmail_users:
            entity:
              class: App\Entity\User
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_vmail_users
            #logout_on_user_change: true
            form_login:
              login_path: login
              check_path: login
              username_parameter: _username
              password_parameter: _password
            logout:
              path: logout
              target: /

    access_control:
        - { path: ^/login, roles: ['PUBLIC_ACCESS'] }
        - { path: ^/admin, roles: ['ROLE_ADMIN'] }
        - { path: ^/manage, roles: ['ROLE_MANAGER'] }
        - { path: ^/user, roles: ['ROLE_USER'] }
    role_hierarchy:
        ROLE_ADMIN: [ROLE_MANAGER, ROLE_USER]
        ROLE_MANAGER: [ROLE_USER]

UserRepository::loadUserByIdentifier方法

public function loadUserByIdentifier(string $username): ?UserInterface
{
    $a=explode('@', $username);
    if (count($a) != 2) {
        return null;
    }
    $user=$a[0];
    $domain=$a[1];
    return $this->createQueryBuilder('u')
        ->leftJoin('u.domain', 'd')
        ->where('u.name = :user AND d.name = :domain')
        ->setParameter('user', $user)
        ->setParameter('domain', $domain)
        ->getQuery()
        ->getOneOrNullResult();
}

排查思路与解决方案

1. 清理生产环境缓存

生产环境默认开启Doctrine元数据缓存和Symfony配置缓存,可能存在旧映射数据残留:

php bin/console cache:clear --env=prod
php bin/console doctrine:cache:clear-metadata --env=prod

2. 检查实体序列化与会话存储

  • 确认User实体正确实现Serializable接口,或通过注解配置了正确的序列化规则,确保用户对象能在会话中正常序列化/反序列化;
  • 检查var/sessions/prod目录权限,确保web服务器用户(www-data)拥有读写权限;
  • 核对config/packages/framework.yaml中的session配置,HTTPS环境下需设置cookie_secure: true,避免Cookie无法传递。

3. 验证用户加载全流程

  • 在UserRepository中添加日志,记录loadUserByIdentifier和loadUserById(若实现)的调用参数与返回结果,确认生产环境下非ID=0用户是否能被正确加载;
  • 检查User实体的getId()方法是否返回正确的主键值,确保身份验证后用户能通过ID被重新加载。

4. 排查权限与角色配置

  • 确认非ID=0域的用户已正确分配ROLE_USER等必要角色,清理角色缓存:
    php bin/console cache:clear --env=prod --pool=security.role_hierarchy.cache
    
  • 临时注释access_control规则,逐步排查是否是权限校验触发的重定向。

5. 排查自定义密码编码器

临时替换为Symfony内置编码器(如bcrypt)测试,排除自定义PassEncoder在生产环境的异常:

password_hashers:
  App\Entity\User:
    algorithm: bcrypt

6. 调整防火墙配置

  • 启用logout_on_user_change: true,测试是否因用户对象属性变更导致会话失效;
  • 临时设置lazy: false,排查懒加载在生产环境的特殊行为。

内容的提问来源于stack exchange,提问作者Oscar Manuel Gómez Senovilla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 21:44:49