python如何从URL中提取哈希片段



我正在使用Spotify的API构建一个python烧瓶应用程序。Spotify API的用户身份验证部分将应用程序id(client_id(、范围等连接到Spotify的最终基础url:https://accounts.spotify.com/authorize?(后面的内容类似于client_id=94857&scope=read(。该URL将用户重定向到验证页面,在那里他们可以批准我的应用程序访问他们的Spotify数据(这意味着现在API应该能够发送请求(。在他们批准之后,他们被带去重定向URL(Spotify API用户(我(的所有者将其输入到应用程序的设置中(,并且在重定向URL之后是一个名为"URL"的变量;access_token";它是一个";散列片段";。我需要这个access_token才能调用API,因为它是用户自定义的必需参数,但我无法访问它,因为它前面有一个"#"。url看起来像这样:

https://myRedirectURL.com/callback#access_token=NwAExz...BV3O2Tk&token_type=载体&expires_ in=3600&状态=123

我可以从我的python函数访问这个url的所有部分,除了包含和跟随"#"字符的信息,这是我需要的信息,因为它没有访问权限。我在另一篇Stackoverflow帖子中读到,后端无法访问哈希片段。

我可以让用户手动复制整个URL,或者只复制访问令牌,并将其输入到我的应用程序中,这样它就有了数据,但我希望避免这种情况,并通过让应用程序提取它来自动化用户的过程,而不是使其成为一个两步式的输入过程。

我获得这些信息的想法是,当用户在URL时,从python运行一个javascript函数,因为javascript react可能能够访问完整的URL。我不知道该怎么做,还想知道是否有其他想法可以获得URL的access_token部分?如果有其他信息可以帮助我,请告诉我。

以下是Spotify API Auth文档:https://developer.spotify.com/documentation/general/guides/authorization-guide/

编辑:感谢您提出使用"授权代码流"而不是"隐式授予"流的想法!这似乎是要走的路。在我看来,不同之处在于使用请求方法并将response_type指定为";代码";所以它不会以散列的形式返回。然而,它仍然不起作用(我得到"无法解析",因为URL中仍然有一个"#"(。我怀疑我确实按照它想要的方式指定了参数,但我已经仔细搜索了一遍,没有看到任何东西。有什么特别的吗?:

from flask import Flask, request, jsonify, render_template, redirect, url_for
import requests
import json
app = Flask(__name__)
CLIENT_ID = "myclientid"
REDIRECR_URI="http://127.0.0.1:5000/callback" #this is the uri specified in my Spotify app
SCOPE='user-read-private%20user-read-playback-state%20user-top-read'
API_ENDPOINT = "https://accounts.spotify.com/authorize"
PARAMS = {  "client_id": CLIENT_ID, 
"response_type": 'code', 
"redirect_uri": REDIRECR_URI,
"state": '123',
"scope": SCOPE,
"show_dialog": False
}
def userAuthURLBuilder(client_id, redirect_uri, scope):
return "https://accounts.spotify.com/authorize?client_id={}&redirect_uri={}&scope={}&response_type=token&state=123".format(client_id, redirect_uri, scope)
builtUrl = userAuthURLBuilder(CLIENT_ID, REDIRECR_URI, SCOPE)
@app.route('/', methods=["GET"])
def getTester():
r = requests.get(url = API_ENDPOINT, params=PARAMS)
data = r.json()
return data
@app.route('/<path:text>', methods=['GET', 'POST'])
def all_routes(text):
if text.startswith('callback'):
try:
params = text.split('&code=')[1]
return params
except:
return "couldn't parse" #this is what I'm currently getting 
else:
return "it errored"

您正试图使用Spotify的隐式授权流,但这可能不是您想要的。正如文件中所说:

隐式授权流适用于完全使用JavaScript实现并在资源所有者的浏览器中运行的客户端。

URL哈希值在服务器端是不可访问的-它们不包括在标头中。获得URL哈希值的唯一方法是从客户端获得——使用现代JavaScript,您可以通过url.hash获得该值。

然而,你真正应该做的是使用Spotify的授权代码流。这将把代码作为查询参数发送,而不是在散列后面发送,您可以使用request.args['code']获得它

更新

在回答您更新的问题时,您应该使用request.args来获取URL查询参数,而不是试图解析出实际的字符串。像这样的东西应该起作用:

@app.route('/callback', methods=['GET', 'POST'])
def all_routes(text):
if request.method == 'GET':
try:
params = request.args
if params and params['code']:
return params['code']
else:
return params['error']
except:
return "couldn't parse"
else:
# not sure why you would use POST here
return

最新更新