【问题标题】:How can python extract a hash fragment from a URL?python如何从URL中提取哈希片段?
【发布时间】:2020-07-18 20:15:38
【问题描述】:

我正在使用 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 之后是一个名为“access_token”的变量,它是一个“哈希片段”。我需要这个 access_token 才能调用 API,因为它是用户自定义的必需参数,但我无法访问它,因为它前面有一个“#”。网址看起来像这样:

https://myRedirectURL.com/callback#access_token=NwAExz...BV3O2Tk&token_type=Bearer&expires_in=3600&state=123

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

我可以让用户手动复制整个 URL 或仅复制访问令牌并将其输入到我的应用程序中,以便它拥有数据,但我想避免这种情况并通过让应用程序提取来为用户自动执行该过程它而不是让它成为一个两步的输入过程。

我获取此信息的想法是在用户位于 URL 时从 python 运行 javascript 函数,因为 javascript react 可能能够访问完整的 URL。我不确定如何执行此操作,并且还想知道是否还有其他方法可以获取 URL 的 access_token 部分?如果有任何其他信息对您有帮助,请告诉我。

这是 Spotify API 身份验证文档: 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"

【问题讨论】:

  • 欢迎。你能申请一些formatting吗?
  • 您似乎启动了错误的 OAuth 流类型。向我们展示生成将用户引导至 Spotify 的 URL 的代码。
  • @KlausD 非常感谢您指出这一点。我现在将使用“授权代码流程”,并发布了我正在使用的代码。您是否有一些可能导致错误的想法?

标签: javascript python api flask spotify


【解决方案1】:

您正在尝试使用 Spotify 的 Implicit Grant Flow,但这可能不是您想要的。正如文档中所说:

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

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

但是,您真正应该做的是使用 Spotify 的 Authorization Code Flow。这会将代码作为查询参数而不是在哈希后面发送,您可以使用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

【讨论】:

  • 非常感谢休!我尝试了您的建议并使用代码编辑了我的问题,但它仍然不足以让我尝试尝试 request.args['code'] 方法,因为 URL / 我作为 get 响应返回的内容无法解析它。我可能做错了?
  • 我更新了我的答案,因为我无法在评论中有用地显示代码示例。
猜你喜欢
  • 1970-01-01
  • 2010-12-19
  • 2012-02-19
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
相关资源
最近更新 更多