【问题标题】:How do I make independent API's?如何制作独立的 API?
【发布时间】:2020-05-03 12:27:08
【问题描述】:

我远不是该主题的专家,我的问题甚至可能毫无意义,但我正在尝试制作一个从我制作的服务器收集数据的应用程序。我编写了一个 Python 脚本,可以登录网站并从中抓取数据。当您向 API 发出 GET 请求时,将调用 Python 函数并将数据放在服务器上供应用程序获取。问题是:每当用户发出 GET 请求(甚至是 POST 请求,以发送 Python 脚本登录所需的凭据)时,服务器都会为每个用户更改。例如,如果用户发布了他的凭据,则字典“凭据”会为每个人更改,如果第二个用户同时发布他的凭据,则字典可能会为两个用户之一获取错误的值。代码如下:

from flask import Flask, request, jsonify
import backend as b

app = Flask(__name__)
credentials = dict()
subjectNames = ['Italiano', 'Inglese', 'Filosofia', 'Storia', 'Matematica', 'Informatica', 'Fisica', 'Scienze', 'Arte', 'Educazione Fisica']

@app.route('/login', methods=['POST'])
def getCredentials():
    if request.method == 'POST':
        username = request.get_json(force=True).get('username')
        password = request.get_json(force=True).get('password')
        credentials['username'] = username
        credentials['password'] = password
        return jsonify({'credentials': credentials})


@app.route ('/creds', methods=['GET'])
def creds():
    return jsonify({'credentials': credentials})

@app.route('/api', methods=['GET'])
def api():
    if request.method == 'GET':
        query = str(request.args['query'])
        if query == 'marks':
            d = {}
            m = b.getFullMarks(b.login(credentials['username'], credentials['password']))
            for i in range(len(subjectNames)):
                d[subjectNames[i]] = m[i]
            return jsonify(d)
        elif query == 'names':
            d = {}
            m = b.getNames(b.login(credentials['username'], credentials['password']))
            for i in range(len(subjectNames)):
                d[subjectNames[i]] = m[i]
            return jsonify(d)
        elif query == 'calendar':
            d = {}
            m = b.calendar(b.login(credentials['username'], credentials['password']))
            d['Calendar'] = m
            return jsonify(d)
        elif query == 'badge':
            d = {}
            m = b.badge(b.login(credentials['username'], credentials['password']))
            d['Badge'] = m
            return jsonify(d)

if __name__ == '__main__':
    app.run()

【问题讨论】:

  • 全局credentials = dict()对于webapps来说是个大问题。你想使用flask-login 或类似的来处理这个

标签: python json api flask request


【解决方案1】:

撇开您将所有凭据保存在内存中这一事实不谈,如果服务器崩溃,您将失去一切。

你不能使用字典来做你想做的事,正如你已经知道的那样,字典只能保存同一个键的单个表示(在我们的例子中,“用户名”)。因此,当第二个用户调用 /login 端点时,您将覆盖前一个端点,反之亦然。

如前所述,大多数应用程序将在成功登录时生成一个令牌,并将其发送回调用用户。 用户会将其添加为即将到来的请求的标头,这允许服务识别调用用户,并执行它需要的任何操作。

您可以寻找现有的实现,或者自己做一些事情。 但最终,您需要将令牌映射到用户,例如:

@app.route('/login', methods=['POST'])
def getCredentials():
    if request.method == 'POST':
        username = request.get_json(force=True).get('username')
        password = request.get_json(force=True).get('password')
        token = generate_token_for_user(username, password)
        credentials[token] = {'username': username, 'password': password}
        return jsonify({'token': token})

在 api 调用中:

@app.route('/api', methods=['GET'])
def api():
    token = request.headers['Authorization'] # assuming you're using this for your token
    creds = credentials.get(token)
    d = {}
    if request.method == 'GET':
        query = str(request.args['query'])
        if query == 'marks':
            m = b.getFullMarks(b.login(creds['username'], creds['password']))
            for i in range(len(subjectNames)):
                d[subjectNames[i]] = m[i]
            return jsonify(d)
        elif query == 'names':
            m = b.getNames(b.login(creds['username'], creds['password']))
            for i in range(len(subjectNames)):
                d[subjectNames[i]] = m[i]
            return jsonify(d)
        elif query == 'calendar':
            m = b.calendar(b.login(creds['username'], creds['password']))
            d['Calendar'] = m
            return jsonify(d)
        elif query == 'badge':
            m = b.badge(b.login(creds['username'], creds['password']))
            d['Badge'] = m
            return jsonify(d)

当然,维护令牌生命周期有点复杂,需要在一段时间后使令牌失效,并且您需要在每个请求上验证它(通常使用中间件),但这是概念.

【讨论】:

  • 所以你是说密码和用户名都应该在标题中?另外,如果您愿意,能否请我解释一下如何实现标头?非常感谢。
  • 嗯,不完全是,常见的方法是通过单向哈希或令牌表示您的用户名和密码,并在其中一个标头中发送令牌。用户使用用户名和密码登录,服务器对用户进行身份验证,并为他提供令牌以在每个 API 请求上发出 API 请求,客户端在指定的标头中发送令牌,服务器验证令牌是否有效。您可以在此处阅读有关标头的更多信息:developer.mozilla.org/en-US/docs/Web/HTTP/Headers
猜你喜欢
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-01
  • 1970-01-01
相关资源
最近更新 更多