Heroku 应用程序在使用 Spotify API 令牌时遇到问题

Posted

技术标签:

【中文标题】Heroku 应用程序在使用 Spotify API 令牌时遇到问题【英文标题】:Heroku app having trouble with Spotify API token 【发布时间】:2020-09-26 01:05:29 【问题描述】:

所以我一直在使用 Flask 创建一个使用 Spotify API 的应用程序,并且授权代码流在我的 localhost 服务器上运行时运行良好。但是,在将应用程序部署到 Heroku 后,有时应用程序会崩溃并在日志中显示“未提供令牌”错误。有时它会完美地工作,但当我玩得更多时它会崩溃。我尝试在本地主机上重做该过程,但似乎没有中断。我将令牌存储在会话中,难道 Heroku 在检索会话变量时遇到问题?

这是烧瓶应用程序代码

#Home view
@app.route('/')
@app.route('/home')
def home():
    return render_template('home.html', title='Home')

#Login view
@app.route('/login', methods=['GET','POST'])
def login():

    AUTH_FIRST = req_auth()
    return redirect(AUTH_FIRST)

#Callback view for Spotify API
@app.route('/callback')
def callback():


    if request.args.get('code'):
        code = request.args.get('code')
        token = req_token(code)
        session['token'] = token

        return redirect(url_for('generate_playlist'))

    else:
        return redirect(url_for('home'))

#Generate playlist view
@app.route('/generate_playlist', methods=['GET', 'POST'])
def generate_playlist():

    if request.method == 'POST':
        levels = int(float(request.form['level']))
        token = session.get('token')
        generate(token, levels)

        return redirect(url_for('success'))

    else:
        return redirect(url_for('generate_playlist'))

这是后端授权代码(我已经注释掉了一些部分以使其更简单,但它仍然不起作用):

client_id = os.environ.get("CLIENT_ID")
client_secret = os.environ.get("CLIENT_SECRET")
redirect_uri = os.environ.get('REDIRECT_URI')

state = ''.join(random.choice(string.ascii_lowercase + string.digits) for n in range(8))
scope = 'user-top-read user-library-read playlist-modify-public'

def req_auth():

    show_dialog = "false"

    AUTH_FIRST_URL = f'https://accounts.spotify.com/authorize?client_id=client_id&response_type=code&redirect_uri=quote("https://surprisify-playlist-generator.herokuapp.com/callback")&show_dialog=show_dialog&state=state&scope=scope'
    return AUTH_FIRST_URL

def req_token(code):

    #B64 encode variables
    client_creds = f"client_id:client_secret"
    client_creds_b64 = base64.b64encode(client_creds.encode())

    #Token data
    token_data = 
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": "https://surprisify-playlist-generator.herokuapp.com/callback"
    

    #Token header
    token_header = 
        "Authorization": f"Basic client_creds_b64.decode()"
    

    #Make request post for token info
    token_json = requests.post('https://accounts.spotify.com/api/token', data=token_data, headers=token_header)
    return token_json.json()['access_token']


    #Checking if token is still valid, otherwise, refresh
    # if token_json.json()['expires_in']:
    #   now = datetime.datetime.now()
    #   expires_in = token_json.json()['expires_in']
    #   expires = now + datetime.timedelta(seconds=expires_in)

    #   if now > expires:

    #       refresh_token_data = 
    #           "grant_type": "refresh_token",
    #           "refresh_token": token_json.json()['refresh_token']
    #       

    #       refresh_token_json = requests.post('https://accounts.spotify.com/api/token', data=refresh_token_data, headers=token_header)
    #       token = refresh_token_json.json()['access_token']

    #       return token
    #   else:

    #       token = token_json.json()['access_token']

    #       return token
    # else:
    #   token = token_json.json()['access_token']

    #   return token

【问题讨论】:

【参考方案1】:

重启浏览器后会出现错误吗? Flask 会话 cookie 会被存储(默认情况下),直到您关闭浏览器。然后,如果您不再次进行身份验证,调用session.get(token) 将返回None,这可能就是您收到错误的原因。您可以尝试在generate_playlist() 中检查令牌是否为None,并要求通过重定向重新进行身份验证。

这是我在自己的项目中成功使用的 Spotify 授权代码流的实现:https://***.com/a/57929497/6538328(方法 2)。

【讨论】:

感谢您的回复。我实际上发现了问题所在;每次程序运行时,我都会生成一个唯一的会话密钥,我猜 Heroku 并没有真正使用它,所以我将会话密钥更改为固定字符串。

以上是关于Heroku 应用程序在使用 Spotify API 令牌时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

Eventlet heroku flasksocketio 应用程序不工作

未初始化的常量 ActiveRecord::DeleteRestrictionError 仅在部署到 Heroku 时

Heroku 上的 Django CSRF_COOKIE_DOMAIN

无需登录即可将曲目添加到播放列表 - API Spotify

Heroku上的现有Ruby on Rails Web应用程序(PostgreSQL),Devise身份验证,需要为移动支持添加Rails API

Heroku:如何通过navicat连接数据库