flask:如何桥接前端和后端服务以呈现 api 身份验证?

bey*_*ity 6 python api flask

flask-restplus 中,我想为我的最小flask API 呈现API 身份验证视图,每当我向服务器发出请求时,第一个API 应该弹出一个保护视图,要求用户在使用API​​ 之前提供自定义令牌值称呼。在使用 api 函数之前,我想出了我的解决方案来制作 API 身份验证弹出视图,但无法正确获取。谁能帮助我让我的代码顺利运行?任何的想法?

我目前的全面实施尝试

这是我执行此任务的部分代码。

from functools import wraps
import requests, json, psycopg2, datetime
from time import time
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from flask_restplus import Resource, Api, abort, fields, inputs, reqparse
from itsdangerous import SignatureExpired, JSONWebSignatureSerializer, BadSignature


class AuthenticationToken:
    def __init__(self, secret_key, expires_in):
        self.secret_key = secret_key
        self.expires_in = expires_in
        self.serializer = JSONWebSignatureSerializer(secret_key)

    def generate_token(self, username):
        info = {
            'username': username,
            'creation_time': time()
        }

        token = self.serializer.dumps(info)
        return token.decode()

    def validate_token(self, token):
        info = self.serializer.loads(token.encode())

        if time() - info['creation_time'] > self.expires_in:
            raise SignatureExpired("The Token has been expired; get a new token")

        return info['username']


SECRET_KEY = "f4b58245-6fd4-4bce-a8a4-27ca37370a3c"
expires_in = 600
auth = AuthenticationToken(SECRET_KEY, expires_in)

db = SQLAlchemy(app)
Run Code Online (Sandbox Code Playgroud)

我几乎为 API 身份验证编写了所有代码,但无法在所需的输出中获得我期望的身份验证弹出视图。

更新:服务器端点的输出

当我http://127.0.0.1:5000/token在服务器端点尝试时,出现Not Found错误。我怎样才能得到我想要的输出?任何的想法?

我想知道如何获得需要令牌才能访问 API 的 API 保护视图。目前,我有一个错误,无法获得我想要的输出,所以我希望SO社区能帮助我解决这个问题。

所需的输出

我想在服务器端点上使用 API 调用之前呈现测试 API 的保护视图。这是我想获得的模型 API 授权视图:

在此处输入图片说明

如何使用 python flask、flask restful 实现这一点?任何想法?谢谢

Dan*_*Dan 1

SO我知道你在做什么,以及上面提到的@B--rian、@Matt L.,社区为所有代码库提供帮助并不是一次性任务。但这就是我所做的,我将指导您如何轻松地完成任务。

我们可以尝试通过划分几个步骤来解决这个任务,但是让我们绕过这一步,我很快就会发布嵌套一个:

from functools import wraps
from time import time
from flask import Flask
from flask import request
from flask_restplus import Resource, Api
from flask_restplus import abort
from flask_restplus import fields
from flask_restplus import inputs
from flask_restplus import reqparse
from psycopg2.extensions import AsIs
import psycopg2, datetime, requests, json
from itsdangerous import SignatureExpired, JSONWebSignatureSerializer, BadSignature

'''
## to get API security key, to do:
import uuid
print(str(uuid.uuid4()))
'''

class AuthenticationToken(object):
    def __init__(self, secret_key, expires_in):
        self.secret_key = secret_key
        self.expires_in = expires_in
        self.serializer = JSONWebSignatureSerializer(secret_key)

    def generate_token(self, username):
        info = {
            'username': username,
            'creation_time': time()
        }
        token = self.serializer.dumps(info)
        return token.decode()

    def validate_token(self, token):
        info = self.serializer.loads(token.encode())

        if time() - info['creation_time'] > self.expires_in:
            raise SignatureExpired("The Token has been expired; get a new token")

        return info['username']

SECRET_KEY = "f4b58245-6fd4-4bce-a8a4-27ca37370a3c"
expires_in = 600
auth = AuthenticationToken(SECRET_KEY, expires_in)

app = Flask(__name__)
api = Api(app,authorizations={
                'API-KEY': {
                    'type': 'apiKey',
                    'in': 'header',
                    'name': 'AUTH-TOKEN'
                }
            },
          security='API-KEY',
          default="API AUTH TOKEN", 
          title="immunoMatch RESTful API", 
          description="Immunomatch ED API Authentication View") 

db = psycopg2.connect(database='test_db', user='postgres', password='password', host='localhost', port="5432")

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):

        token = request.headers.get('AUTH-TOKEN')
        if not token:
            abort(401, 'Authentication token is missing')

        try:
            user = auth.validate_token(token)
        except SignatureExpired as e:
            abort(401, e.message)
        except BadSignature as e:
            abort(401, e.message)

        return f(*args, **kwargs)
    return decorated

credential_model = api.model('credential', {
    'username': fields.String(required=True),
    'password': fields.String(required=True)
})

credential_parser = reqparse.RequestParser()
credential_parser.add_argument('username', type=str)
credential_parser.add_argument('password', type=str)

@api.route('/token')
class Token(Resource):
    @api.expect(credential_parser, validate=True)
    def get(self):
        args = credential_parser.parse_args()
        username = args.get('username')
        password = args.get('password')
        cursor = db.cursor()
        cursor.execute('SELECT * FROM public.authorized_user_table')
        user = cursor.fetchone()

        if username != user[1]:
            api.abort(404, "Username: {} doesn't exist".format(username))
        if password != user[2]:
            api.abort(401, "Wrong password")
        return {"token": auth.generate_token(username)}

if __name__ == '__main__':
    db = psycopg2.connect(database='test_db', user='postgres', password='password', host='localhost', port="5432")
    app.run(debug=True)
Run Code Online (Sandbox Code Playgroud)

我建议尝试消化@B--rian、@Matt L 在他们的帖子中提到的内容,我认为@Matt L 确实指出了一些值得你思考的东西,他们的建议很好,除了没有给出太多的编码尝试。但一旦我想办法休息,我就会回到你身边。