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

Laravel API跨端点获取Spotify第三方授权令牌问题求助

Laravel集成Spotify认证:API端点无法获取Session中令牌的解决方案

问题场景

我正在为Laravel项目集成Spotify认证,目的是获取Spotify Token来调用用户相关功能(比如给已关联用户的播放列表添加曲目)。目前已完成OAuth认证流程,在回调端点中可以通过Laravel Socialite获取用户信息并存入Session,但在/api/genres这类API端点中,无法获取Session里的用户令牌——调用Socialite::driver('spotify')->user()会抛出“Invalid Exception state .. No session found”异常。

相关代码

Spotify认证路由

Route::prefix('/spotify')->group(function () {
    Route::get('auth/redirect', function () {
        return Socialite::driver('spotify')
            ->setScopes(SpotifyController::READ_ACCES)
            ->redirect();
    });

    Route::get('auth/callback', function () {
        return response()->json(['message' => "Utilisateur connecté à spotify"]);
    });
});

Genres API路由

Route::prefix('genres')->group(function() {
    Route::get('', [GenreController::class, 'index'])->name('genres.index');
});

GenreController代码

class GenreController extends Controller
{
    protected function index(Request $request)
    {
        dd(Socialite::driver('spotify')->user());
    }
}

Session中间件配置

'web' => [
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \App\Http\Middleware\VerifyCsrfToken::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

'api' => [
    \App\Http\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

核心原因

API端点默认是无状态设计,即便你在api中间件组里加了StartSession,前端调用API时通常不会自动携带Session Cookie(尤其是跨域或单页应用场景),导致Session无法在Web路由和API路由间共享。而Socialite的user()方法完全依赖Session存储的OAuth状态和令牌信息,所以在API里调用会直接报错。

推荐解决方案:将Spotify令牌持久化到数据库

这是生产环境最可靠的方案,步骤如下:

1. 准备存储令牌的数据库字段

如果用户已有账号,直接在users表添加以下字段:

  • spotify_access_token(字符串,存访问令牌)
  • spotify_refresh_token(字符串,存刷新令牌)
  • spotify_token_expires_at(时间戳,存令牌过期时间)

或者创建单独的spotify_profiles关联表,通过用户ID关联存储上述信息。

2. 修改回调端点,保存令牌到数据库

在回调里获取完整的Socialite用户对象,提取令牌信息存入数据库:

Route::get('auth/callback', function () {
    $spotifyUser = Socialite::driver('spotify')->user();
    
    // 关联到当前登录用户
    auth()->user()->update([
        'spotify_access_token' => $spotifyUser->token,
        'spotify_refresh_token' => $spotifyUser->refreshToken,
        'spotify_token_expires_at' => now()->addSeconds($spotifyUser->expiresIn),
    ]);
    
    return response()->json(['message' => "用户已关联Spotify"]);
});

3. 在API端点中从数据库获取并使用令牌

不再依赖Socialite的user()方法,直接从当前用户的数据库记录中读取令牌,还可以自动处理令牌过期刷新:

class GenreController extends Controller
{
    public function index(Request $request)
    {
        $user = $request->user();
        $spotifyToken = $user->spotify_access_token;
        
        // 检查令牌是否过期,自动刷新
        if (now()->greaterThan($user->spotify_token_expires_at)) {
            $newTokenData = Socialite::driver('spotify')->refreshToken($user->spotify_refresh_token);
            
            $user->update([
                'spotify_access_token' => $newTokenData['access_token'],
                'spotify_token_expires_at' => now()->addSeconds($newTokenData['expires_in']),
            ]);
            $spotifyToken = $newTokenData['access_token'];
        }
        
        // 用令牌调用Spotify API示例
        $response = Http::withToken($spotifyToken)
            ->get('https://api.spotify.com/v1/me/top/artists', [
                'time_range' => 'medium_term',
                'limit' => 50,
            ]);
        
        return response()->json($response->json());
    }
}

4. 给API路由添加认证中间件

确保只有登录用户能访问这些需要Spotify令牌的API:

Route::prefix('genres')->middleware('auth:api')->group(function() {
    Route::get('', [GenreController::class, 'index'])->name('genres.index');
});

其他可选方案(不推荐生产环境)

  • 强制API使用Session:如果是同域前端应用,确保请求携带X-CSRF-TOKEN和Session Cookie,但不符合RESTful无状态设计,跨域场景配置复杂。
  • 返回令牌给前端存储:回调时将Spotify令牌返回给前端,前端每次调用API时在请求头携带(如Authorization: Bearer {spotify_token}),但令牌易被盗取,安全风险高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:59:56