使用Spotipy的SpotifyOAuth无法获取用户信息,授权流程异常
问题分析与解决方案
核心问题
ClientCredentials流的局限性:该模式仅用于访问Spotify公开数据,无法获取用户私有信息(如current_user()),必须使用授权码流(SpotifyOAuth),但你当前的代码存在两个关键错误:- 每次请求都重新实例化
SpotifyOAuth,未复用或存储用户已授权的token,导致每次调用都触发全新的授权流程,Postman因此反复打开授权页面。 - 视图返回语句
JsonResponse(test, safe=False)完全错误,test是函数对象,并非要返回的数据。
- 每次请求都重新实例化
修复步骤
1. 扩展用户模型存储Spotify Token
首先需要在用户模型中添加字段,用于保存用户的Spotify授权token(支持过期自动刷新):
from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): # 存储Spotify返回的token信息(含access_token、refresh_token等) spotify_token = models.JSONField(null=True, blank=True)
2. 新增授权引导与回调视图
单独拆分授权流程,避免每次请求重复触发授权:
from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import permissions import spotipy from spotipy.oauth2 import SpotifyOAuth from django.conf import settings # 引导用户跳转到Spotify授权页面 @api_view(['GET']) @permission_classes([permissions.IsAuthenticated]) def spotify_auth(request): sp_oauth = SpotifyOAuth( client_id=settings.SPOTIFY_CLIENT_ID, client_secret=settings.SPOTIFY_CLIENT_SECRET, redirect_uri=settings.SPOTIPY_REDIRECT_URI, # 根据需求添加权限,获取用户信息至少需要user-read-private scope="user-read-private user-read-email" ) auth_url = sp_oauth.get_authorize_url() return Response({"auth_url": auth_url}) # 接收Spotify授权回调,存储token到用户模型 @api_view(['GET']) @permission_classes([permissions.IsAuthenticated]) def spotify_callback(request): code = request.GET.get('code') if not code: return Response({"error": "授权码缺失"}, status=400) sp_oauth = SpotifyOAuth( client_id=settings.SPOTIFY_CLIENT_ID, client_secret=settings.SPOTIFY_CLIENT_SECRET, redirect_uri=settings.SPOTIPY_REDIRECT_URI ) token_info = sp_oauth.get_access_token(code) # 将token存入当前用户 request.user.spotify_token = token_info request.user.save() return Response({"message": "Spotify授权成功"})
3. 重构原测试视图
复用已存储的token,避免重复授权:
@api_view(['GET']) @permission_classes([permissions.IsAuthenticated]) def test(request): # 检查用户是否已完成Spotify授权 if not request.user.spotify_token: return Response({"error": "请先调用/spotify-auth完成授权"}, status=400) sp_oauth = SpotifyOAuth( client_id=settings.SPOTIFY_CLIENT_ID, client_secret=settings.SPOTIFY_CLIENT_SECRET, redirect_uri=settings.SPOTIPY_REDIRECT_URI ) token_info = request.user.spotify_token # 检查token是否过期,过期则自动刷新 if sp_oauth.is_token_expired(token_info): token_info = sp_oauth.refresh_access_token(token_info['refresh_token']) request.user.spotify_token = token_info request.user.save() # 用有效token初始化Spotipy客户端 sp = spotipy.Spotify(auth=token_info['access_token']) # 测试获取公开数据与用户私有数据 urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu' artist = sp.artist(urn) user = sp.current_user() return Response({ "artist": artist, "current_user": user })
关键注意事项
- 确保
SPOTIPY_REDIRECT_URI已在Spotify开发者后台的应用设置中正确配置,且与代码中的地址完全一致。 - 权限
scope需根据实际需求添加,比如获取用户播放列表需额外添加playlist-read-private等权限。 - Postman测试流程:先调用
/spotify-auth获取授权URL,在浏览器打开完成授权后,回调会自动存储token,之后再调用/test即可正常获取用户信息,不会重复弹出授权页面。
内容的提问来源于stack exchange,提问作者Mymy la brute
相关产品推荐
相关产品推荐

