Symfony 4.4 PHPUnit测试无法认证用户,如何不通过登录表单完成鉴权
Symfony4.4 PHPUnit单元测试无表单模拟用户认证解决方案
问题根因
原方案失效的核心原因如下:
- 多Guard认证器场景下,手动创建的
PostAuthenticationGuardToken未匹配安全层校验规则,有效性校验失败后被清空 - 自定义
session_user_provider的逻辑和token生成规则不匹配,导致从session反序列化token后无法加载到有效用户
修正方案(无需调用登录表单/接口)
方案1:直接注入有效token到安全上下文(适配绝大多数场景)
修改你的logIn方法,直接操作安全上下文存储token,代码如下:
private function logIn() { // 加载测试用户,确认该用户真实存在、状态有效 $user = self::$container->get(EntityManagerInterface::class) ->getRepository(User::class) ->findOneByMail('test106@test.com'); // 创建有效认证token $token = new PostAuthenticationGuardToken( $user, 'main', // 对应你的防火墙名称 $user->getRoles() // 直接使用用户实体的角色,不要手动写死 ); // 注入token到安全存储 self::$container->get('security.token_storage')->setToken($token); // 同步token到session,适配多请求测试场景 $session = self::$container->get('session'); $session->set('_security_main', serialize($token)); $session->save(); // 设置session cookie,跨请求时保留认证状态 $cookie = new Cookie($session->getName(), $session->getId()); $this->client->getCookieJar()->set($cookie); }
校验要求:
- 你的
User实体必须正确实现Symfony\Component\Security\Core\User\UserInterface接口,serialize()/unserialize()、getRoles()、getPassword()、4.4版本中对应的用户标识方法getUsername()返回值符合预期 - 测试环境的
security.yaml中main防火墙不要开启stateless: true配置,否则会忽略session中的token
方案2:使用现有Bearer认证器(无需操作session)
你已经配置了BearerTokenAuthenticator,如果测试的接口支持Bearer认证,直接在请求头携带有效token即可:
public function testJsonUserEndpoint() { // 提前获取测试用户的有效Bearer token,可直接从数据库查询或生成 $testUserToken = '测试用户的有效token值'; $crawler = $this->client->request( 'GET', '/json/user', [], [], ['HTTP_Authorization' => 'Bearer ' . $testUserToken] ); $this->assertNotContains('invalid_credentials', $this->client->getResponse()->getContent()); }
内容的提问来源于stack exchange,提问作者amacrobert
相关产品推荐
相关产品推荐

