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

Symfony 6.2使用AccessToken无法完成用户认证求助

Symfony 6.2 AccessToken无状态认证返回401问题排查与解决

问题描述

基于Symfony 6.2构建API应用,采用AccessToken实现无状态认证,已按官方文档实现AccessTokenHandler类并配置security.yaml。数据库中存在有效用户及关联令牌,请求可正常进入AccessTokenHandler::getUserBadgeFrom方法,且能返回正确的令牌及关联用户,但请求始终返回401 Unauthorized状态码,响应头包含WWW-Authenticate: Bearer error="invalid_token",error_description="Invalid credentials."。

现有代码

AccessTokenHandler类

<?php
# src\Security\AccessTokenHandler.php

namespace App\Security;

use App\Repository\AccessTokenRepository;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;

class AccessTokenHandler implements AccessTokenHandlerInterface {
    public function __construct( private AccessTokenRepository $repository
    ) {
    }

    public function getUserBadgeFrom( string $accessToken ): UserBadge {
        // 查询数据库验证令牌
        $accessToken = $this->repository->findValidToken($accessToken);

        if ( NULL === $accessToken || !$accessToken->isValid() ) {
            throw new BadCredentialsException( 'Invalid credentials.' );
        }

        // 返回包含用户标识的UserBadge
        return new UserBadge( $accessToken->getUserId() );
    }
}

security.yaml配置

security:
    # 用户密码哈希配置
    password_hashers:
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
    # 用户提供者配置
    providers:
        access_token_provider:
            entity:
                class: App\Entity\AccessToken
                property: tokenValue
    firewalls:
        main:
            lazy: true
            provider: access_token_provider
            stateless: true
            pattern: ^/api
            access_token:
                token_extractors: header
                token_handler: App\Security\AccessTokenHandler
    access_control:
        - { path: ^/api, roles: ROLE_ADMIN }

问题原因

用户提供者配置错误:当前配置的access_token_provider是针对AccessToken实体的,但AccessTokenHandler返回的UserBadge携带的是用户ID,Symfony需要通过用户提供者加载对应的User实体而非AccessToken实体,导致无法匹配到有效用户,最终认证失败。

解决方案

1. 修改security.yaml中的用户提供者配置

将用户提供者改为针对User实体,并确保防火墙使用该提供者:

security:
    password_hashers:
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
    providers:
        # 替换为User实体的提供者
        app_user_provider:
            entity:
                class: App\Entity\User
                property: id # 与UserBadge返回的用户ID匹配
    firewalls:
        main:
            lazy: true
            provider: app_user_provider # 使用新的用户提供者
            stateless: true
            pattern: ^/api
            access_token:
                token_extractors: header
                token_handler: App\Security\AccessTokenHandler
    access_control:
        - { path: ^/api, roles: ROLE_ADMIN }

2. 确保User实体符合要求

你的User实体必须实现Symfony\Component\Security\Core\User\UserInterface接口,包含getRoles()、getUserIdentifier()等必要方法;若涉及密码认证,还需实现PasswordAuthenticatedUserInterface接口。

3. 验证用户ID的有效性

确认AccessToken::getUserId()返回的是User实体的有效ID,且数据库中存在对应的用户记录。

内容的提问来源于stack exchange,提问作者Denis O.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:09:26