使用 spotipy 将 Spotify 令牌存储在烧瓶 session 中?
Storing Spotify token in flask session using spotipy?
我可能对 flask session 的工作原理有不好的理解,但我正在尝试使用 SpotiPY 和授权代码流程生成 Spotify API 访问令牌,并且将其存储在 Flask 的 session 存储中。
该程序似乎无法存储它,因此稍后在尝试调用它时遇到错误。这是带有图像和标题的直观解释:https://imgur.com/a/KiYZFiQ
这是主要的服务器脚本:
from flask import Flask, render_template, redirect, request, session, make_response,session,redirect
import spotipy
import spotipy.util as util
from credentz import *
app = Flask(__name__)
app.secret_key = SSK
@app.route("/")
def verify():
session.clear()
session['toke'] = util.prompt_for_user_token("", scope='playlist-modify-private,playlist-modify-public,user-top-read', client_id=CLI_ID, client_secret=CLI_SEC, redirect_uri="http://127.0.0.1:5000/index")
return redirect("/index")
@app.route("/index")
def index():
return render_template("index.html")
@app.route("/go", methods=['POST'])
def go():
data=request.form
sp = spotipy.Spotify(auth=session['toke'])
response = sp.current_user_top_artists(limit=data['num_tracks'], time_range=data['time_range'])
return render_template("results.html",data=data)
if __name__ == "__main__":
app.run(debug=True)
这是两个 html 文件:Index.html, Results.html
一些值得注意的事情:
Credentz
存储所有私人信息,包括 SSK
、CLI_SEC
和 CLI_ID
。
如果我在没有 web-browser 交互的 non-flask 环境中执行,spotipy 请求工作正常。
我可以在 session 存储中存储其他东西,稍后再调用它,只是由于某种原因不能访问令牌。
我最好的猜测是在 Spotify api 重定向页面之前页面没有时间存储它,但不确定。
非常感谢任何帮助,谢谢!
你是对的,Spotify 在添加令牌之前重定向你,因此结束了该功能的执行。所以你需要添加一个回调步骤来在你被重定向后获取身份验证令牌。
Spotitpy 的 util.prompt_for_user_token 方法并非设计用于网络服务器,因此您最好的办法是自己实施身份验证流程,然后在获得令牌后使用 spotipy。幸运的是,spotify 授权流程非常简单且易于实施。
方法一:自己实现认证流程:
from flask import Flask, render_template, redirect, request, session, make_response,session,redirect
import spotipy
import spotipy.util as util
from credentz import *
import requests
app = Flask(__name__)
app.secret_key = SSK
API_BASE = 'https://accounts.spotify.com'
# Make sure you add this to Redirect URIs in the setting of the application dashboard
REDIRECT_URI = "http://127.0.0.1:5000/api_callback"
SCOPE = 'playlist-modify-private,playlist-modify-public,user-top-read'
# Set this to True for testing but you probably want it set to False in production.
SHOW_DIALOG = True
# authorization-code-flow Step 1. Have your application request authorization;
# the user logs in and authorizes access
@app.route("/")
def verify():
auth_url = f'{API_BASE}/authorize?client_id={CLI_ID}&response_type=code&redirect_uri={REDIRECT_URI}&scope={SCOPE}&show_dialog={SHOW_DIALOG}'
print(auth_url)
return redirect(auth_url)
@app.route("/index")
def index():
return render_template("index.html")
# authorization-code-flow Step 2.
# Have your application request refresh and access tokens;
# Spotify returns access and refresh tokens
@app.route("/api_callback")
def api_callback():
session.clear()
code = request.args.get('code')
auth_token_url = f"{API_BASE}/api/token"
res = requests.post(auth_token_url, data={
"grant_type":"authorization_code",
"code":code,
"redirect_uri":"http://127.0.0.1:5000/api_callback",
"client_id":CLI_ID,
"client_secret":CLI_SEC
})
res_body = res.json()
print(res.json())
session["toke"] = res_body.get("access_token")
return redirect("index")
# authorization-code-flow Step 3.
# Use the access token to access the Spotify Web API;
# Spotify returns requested data
@app.route("/go", methods=['POST'])
def go():
data = request.form
sp = spotipy.Spotify(auth=session['toke'])
response = sp.current_user_top_artists(limit=data['num_tracks'], time_range=data['time_range'])
return render_template("results.html", data=data)
if __name__ == "__main__":
app.run(debug=True)
另一方面,我们可以稍微作弊并使用 spotipy 本身正在使用的方法来为我们节省一些代码。
方法 2:使用 spotipy 实施身份验证流程(以及自定义令牌管理)。oauth2.SpotifyOAuth 方法:
from flask import Flask, render_template, redirect, request, session, make_response,session,redirect
import spotipy
import spotipy.util as util
from credentz import *
import time
import json
app = Flask(__name__)
app.secret_key = SSK
API_BASE = 'https://accounts.spotify.com'
# Make sure you add this to Redirect URIs in the setting of the application dashboard
REDIRECT_URI = "http://127.0.0.1:5000/api_callback"
SCOPE = 'playlist-modify-private,playlist-modify-public,user-top-read'
# Set this to True for testing but you probaly want it set to False in production.
SHOW_DIALOG = True
# authorization-code-flow Step 1. Have your application request authorization;
# the user logs in and authorizes access
@app.route("/")
def verify():
# Don't reuse a SpotifyOAuth object because they store token info and you could leak user tokens if you reuse a SpotifyOAuth object
sp_oauth = spotipy.oauth2.SpotifyOAuth(client_id = CLI_ID, client_secret = CLI_SEC, redirect_uri = REDIRECT_URI, scope = SCOPE)
auth_url = sp_oauth.get_authorize_url()
print(auth_url)
return redirect(auth_url)
@app.route("/index")
def index():
return render_template("index.html")
# authorization-code-flow Step 2.
# Have your application request refresh and access tokens;
# Spotify returns access and refresh tokens
@app.route("/api_callback")
def api_callback():
# Don't reuse a SpotifyOAuth object because they store token info and you could leak user tokens if you reuse a SpotifyOAuth object
sp_oauth = spotipy.oauth2.SpotifyOAuth(client_id = CLI_ID, client_secret = CLI_SEC, redirect_uri = REDIRECT_URI, scope = SCOPE)
session.clear()
code = request.args.get('code')
token_info = sp_oauth.get_access_token(code)
# Saving the access token along with all other token related info
session["token_info"] = token_info
return redirect("index")
# authorization-code-flow Step 3.
# Use the access token to access the Spotify Web API;
# Spotify returns requested data
@app.route("/go", methods=['POST'])
def go():
session['token_info'], authorized = get_token(session)
session.modified = True
if not authorized:
return redirect('/')
data = request.form
sp = spotipy.Spotify(auth=session.get('token_info').get('access_token'))
response = sp.current_user_top_tracks(limit=data['num_tracks'], time_range=data['time_range'])
# print(json.dumps(response))
return render_template("results.html", data=data)
# Checks to see if token is valid and gets a new token if not
def get_token(session):
token_valid = False
token_info = session.get("token_info", {})
# Checking if the session already has a token stored
if not (session.get('token_info', False)):
token_valid = False
return token_info, token_valid
# Checking if token has expired
now = int(time.time())
is_token_expired = session.get('token_info').get('expires_at') - now < 60
# Refreshing token if it has expired
if (is_token_expired):
# Don't reuse a SpotifyOAuth object because they store token info and you could leak user tokens if you reuse a SpotifyOAuth object
sp_oauth = spotipy.oauth2.SpotifyOAuth(client_id = CLI_ID, client_secret = CLI_SEC, redirect_uri = REDIRECT_URI, scope = SCOPE)
token_info = sp_oauth.refresh_access_token(session.get('token_info').get('refresh_token'))
token_valid = True
return token_info, token_valid
if __name__ == "__main__":
app.run(debug=True)
我认为这两种方法都同样有效,请选择您认为更容易理解的方法。
确保在 Spotify 应用程序控制面板中更新授权的重定向 URI。
有关详细信息,请参阅 spotify 文档:https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow
我可能对 flask session 的工作原理有不好的理解,但我正在尝试使用 SpotiPY 和授权代码流程生成 Spotify API 访问令牌,并且将其存储在 Flask 的 session 存储中。
该程序似乎无法存储它,因此稍后在尝试调用它时遇到错误。这是带有图像和标题的直观解释:https://imgur.com/a/KiYZFiQ
这是主要的服务器脚本:
from flask import Flask, render_template, redirect, request, session, make_response,session,redirect
import spotipy
import spotipy.util as util
from credentz import *
app = Flask(__name__)
app.secret_key = SSK
@app.route("/")
def verify():
session.clear()
session['toke'] = util.prompt_for_user_token("", scope='playlist-modify-private,playlist-modify-public,user-top-read', client_id=CLI_ID, client_secret=CLI_SEC, redirect_uri="http://127.0.0.1:5000/index")
return redirect("/index")
@app.route("/index")
def index():
return render_template("index.html")
@app.route("/go", methods=['POST'])
def go():
data=request.form
sp = spotipy.Spotify(auth=session['toke'])
response = sp.current_user_top_artists(limit=data['num_tracks'], time_range=data['time_range'])
return render_template("results.html",data=data)
if __name__ == "__main__":
app.run(debug=True)
这是两个 html 文件:Index.html, Results.html
一些值得注意的事情:
Credentz
存储所有私人信息,包括SSK
、CLI_SEC
和CLI_ID
。如果我在没有 web-browser 交互的 non-flask 环境中执行,spotipy 请求工作正常。
我可以在 session 存储中存储其他东西,稍后再调用它,只是由于某种原因不能访问令牌。
我最好的猜测是在 Spotify api 重定向页面之前页面没有时间存储它,但不确定。
非常感谢任何帮助,谢谢!
你是对的,Spotify 在添加令牌之前重定向你,因此结束了该功能的执行。所以你需要添加一个回调步骤来在你被重定向后获取身份验证令牌。
Spotitpy 的 util.prompt_for_user_token 方法并非设计用于网络服务器,因此您最好的办法是自己实施身份验证流程,然后在获得令牌后使用 spotipy。幸运的是,spotify 授权流程非常简单且易于实施。
方法一:自己实现认证流程:
from flask import Flask, render_template, redirect, request, session, make_response,session,redirect
import spotipy
import spotipy.util as util
from credentz import *
import requests
app = Flask(__name__)
app.secret_key = SSK
API_BASE = 'https://accounts.spotify.com'
# Make sure you add this to Redirect URIs in the setting of the application dashboard
REDIRECT_URI = "http://127.0.0.1:5000/api_callback"
SCOPE = 'playlist-modify-private,playlist-modify-public,user-top-read'
# Set this to True for testing but you probably want it set to False in production.
SHOW_DIALOG = True
# authorization-code-flow Step 1. Have your application request authorization;
# the user logs in and authorizes access
@app.route("/")
def verify():
auth_url = f'{API_BASE}/authorize?client_id={CLI_ID}&response_type=code&redirect_uri={REDIRECT_URI}&scope={SCOPE}&show_dialog={SHOW_DIALOG}'
print(auth_url)
return redirect(auth_url)
@app.route("/index")
def index():
return render_template("index.html")
# authorization-code-flow Step 2.
# Have your application request refresh and access tokens;
# Spotify returns access and refresh tokens
@app.route("/api_callback")
def api_callback():
session.clear()
code = request.args.get('code')
auth_token_url = f"{API_BASE}/api/token"
res = requests.post(auth_token_url, data={
"grant_type":"authorization_code",
"code":code,
"redirect_uri":"http://127.0.0.1:5000/api_callback",
"client_id":CLI_ID,
"client_secret":CLI_SEC
})
res_body = res.json()
print(res.json())
session["toke"] = res_body.get("access_token")
return redirect("index")
# authorization-code-flow Step 3.
# Use the access token to access the Spotify Web API;
# Spotify returns requested data
@app.route("/go", methods=['POST'])
def go():
data = request.form
sp = spotipy.Spotify(auth=session['toke'])
response = sp.current_user_top_artists(limit=data['num_tracks'], time_range=data['time_range'])
return render_template("results.html", data=data)
if __name__ == "__main__":
app.run(debug=True)
另一方面,我们可以稍微作弊并使用 spotipy 本身正在使用的方法来为我们节省一些代码。
方法 2:使用 spotipy 实施身份验证流程(以及自定义令牌管理)。oauth2.SpotifyOAuth 方法:
from flask import Flask, render_template, redirect, request, session, make_response,session,redirect
import spotipy
import spotipy.util as util
from credentz import *
import time
import json
app = Flask(__name__)
app.secret_key = SSK
API_BASE = 'https://accounts.spotify.com'
# Make sure you add this to Redirect URIs in the setting of the application dashboard
REDIRECT_URI = "http://127.0.0.1:5000/api_callback"
SCOPE = 'playlist-modify-private,playlist-modify-public,user-top-read'
# Set this to True for testing but you probaly want it set to False in production.
SHOW_DIALOG = True
# authorization-code-flow Step 1. Have your application request authorization;
# the user logs in and authorizes access
@app.route("/")
def verify():
# Don't reuse a SpotifyOAuth object because they store token info and you could leak user tokens if you reuse a SpotifyOAuth object
sp_oauth = spotipy.oauth2.SpotifyOAuth(client_id = CLI_ID, client_secret = CLI_SEC, redirect_uri = REDIRECT_URI, scope = SCOPE)
auth_url = sp_oauth.get_authorize_url()
print(auth_url)
return redirect(auth_url)
@app.route("/index")
def index():
return render_template("index.html")
# authorization-code-flow Step 2.
# Have your application request refresh and access tokens;
# Spotify returns access and refresh tokens
@app.route("/api_callback")
def api_callback():
# Don't reuse a SpotifyOAuth object because they store token info and you could leak user tokens if you reuse a SpotifyOAuth object
sp_oauth = spotipy.oauth2.SpotifyOAuth(client_id = CLI_ID, client_secret = CLI_SEC, redirect_uri = REDIRECT_URI, scope = SCOPE)
session.clear()
code = request.args.get('code')
token_info = sp_oauth.get_access_token(code)
# Saving the access token along with all other token related info
session["token_info"] = token_info
return redirect("index")
# authorization-code-flow Step 3.
# Use the access token to access the Spotify Web API;
# Spotify returns requested data
@app.route("/go", methods=['POST'])
def go():
session['token_info'], authorized = get_token(session)
session.modified = True
if not authorized:
return redirect('/')
data = request.form
sp = spotipy.Spotify(auth=session.get('token_info').get('access_token'))
response = sp.current_user_top_tracks(limit=data['num_tracks'], time_range=data['time_range'])
# print(json.dumps(response))
return render_template("results.html", data=data)
# Checks to see if token is valid and gets a new token if not
def get_token(session):
token_valid = False
token_info = session.get("token_info", {})
# Checking if the session already has a token stored
if not (session.get('token_info', False)):
token_valid = False
return token_info, token_valid
# Checking if token has expired
now = int(time.time())
is_token_expired = session.get('token_info').get('expires_at') - now < 60
# Refreshing token if it has expired
if (is_token_expired):
# Don't reuse a SpotifyOAuth object because they store token info and you could leak user tokens if you reuse a SpotifyOAuth object
sp_oauth = spotipy.oauth2.SpotifyOAuth(client_id = CLI_ID, client_secret = CLI_SEC, redirect_uri = REDIRECT_URI, scope = SCOPE)
token_info = sp_oauth.refresh_access_token(session.get('token_info').get('refresh_token'))
token_valid = True
return token_info, token_valid
if __name__ == "__main__":
app.run(debug=True)
我认为这两种方法都同样有效,请选择您认为更容易理解的方法。
确保在 Spotify 应用程序控制面板中更新授权的重定向 URI。
有关详细信息,请参阅 spotify 文档:https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow