如何制作独立的API?

时间:2020-05-03 12:27:08

标签: python json api flask request

我远不是该主题的专家,我的问题甚至可能没有任何意义,但我正在尝试开发一个可从我制造的服务器中收集数据的应用程序。我制作了一个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()

1 个答案:

答案 0 :(得分: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)

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