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
相关产品推荐
相关产品推荐

