简体   繁体   English

在使用 Flask-JWT-Extended 和 Flask-Restful 时遇到问题

[英]Having issues using Flask-JWT-Extended with Flask-Restful

I'm building an API using Flask-Restful following the steps from the book "Python API Fundamentals".我正在按照“Python API Fundamentals”一书中的步骤使用 Flask-Restful 构建 API。 The problem I'm having is that I'm unable to get a token.我遇到的问题是我无法获得令牌。 My code which is an edited replica of that which is in the book is throwing the following error whenever I test it on Postman我的代码是书中内容的编辑副本,每当我在 Postman 上进行测试时,它都会抛出以下错误

127.0.0.1 - - [01/Aug/2022 13:26:49] "POST /token HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 2091, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 2076, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 271, in error_router
    return original_handler(e)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 1519, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 271, in error_router
    return original_handler(e)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 1517, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 1503, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 467, in wrapper
    resp = resource(*args, **kwargs)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\views.py", line 84, in view
    return current_app.ensure_sync(self.dispatch_request)(*args, **kwargs)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 582, in dispatch_request
    resp = meth(*args, **kwargs)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\smilecook\resources\token.py", line 24, in post
    access_token = create_access_token(identity=user.id)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\utils.py", line 157, in create_access_token
    return jwt_manager._create_access_token(identity, fresh, expires_delta, user_claims)
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\jwt_manager.py", line 469, in _create_access_token
    access_token = encode_access_token(
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\tokens.py", line 76, in encode_access_token
    return _encode_jwt(token_data, expires_delta, secret, algorithm,
  File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\tokens.py", line 31, in _encode_jwt
    json_encoder=json_encoder).decode('utf-8')
AttributeError: 'str' object has no attribute 'decode'

Here's my requirements.txt这是我的要求.txt

Flask==2.1.3
Flask-RESTful==0.3.9
httpie==3.2.1
Flask-SQLAlchemy==2.5.1
Flask-Migrate==3.1.0
psycopg2-binary==2.9.3
passlib==1.7.4
Flask-JWT-Extended==3.20.0
Werkzeug==2.0

and the codes that I think is causing the issue以及我认为导致问题的代码

from http import HTTPStatus
from flask import request
from flask_restful import Resource
from flask_jwt_extended import create_access_token

from utils import check_password
from models.user import User


class TokenResource(Resource):

    def post(self):

        json_data = request.get_json()

        email = json_data.get('email')
        password = json_data.get('password')

        user = User.get_by_email(email=email)

        if not user or not check_password(password, user.password):
            return {'message': 'username or password is incorrect'}, HTTPStatus.UNAUTHORIZED

        access_token = create_access_token(identity=user.id)

        return {'access_token': access_token}, HTTPStatus.OK

from flask import request
from flask_restful import Resource
from flask_jwt_extended import jwt_optional, get_jwt_identity
from http import HTTPStatus

from utils import hash_password
from models.user import User


class UserListResource(Resource):
    def post(self):
        json_data = request.get_json()

        username = json_data.get('username')
        email = json_data.get('email')
        non_hash_password = json_data.get('password')

        if User.get_by_username(username):
            return {'message': 'username already used'}, HTTPStatus.BAD_REQUEST

        if User.get_by_email(email):
            return {'message': 'email already used'}, HTTPStatus.BAD_REQUEST

        password = hash_password(non_hash_password)

        user = User(
            username=username,
            email=email,
            password=password
        )

        user.save()

        data = {
            'id': user.id,
            'username': user.username,
            'email': user.email
        }

        return data, HTTPStatus.CREATED


class UserResource(Resource):

    @jwt_optional
    def get(self, username):

        user = User.get_by_username(username=username)

        if user is None:
            return {'message': 'user not found'}, HTTPStatus.NOT_FOUND

        current_user = get_jwt_identity()

        if current_user == user.id:
            data = {
                'id': user.id,
                'username': user.username,
                'email': user.email,
            }

        else:
            data = {
                'id': user.id,
                'username': user.username,
            }

        return data, HTTPStatus.OK

from flask import Flask
from flask_migrate import Migrate
from flask_restful import Api

from config import Config
from extensions import db, jwt


from resources.user import UserListResource, UserResource
from resources.token import TokenResource
from resources.recipe import RecipeListResource, RecipeResource, RecipePublishResource


def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)

    register_extensions(app)
    register_resources(app)

    return app


def register_extensions(app):
    db.init_app(app)
    migrate = Migrate(app, db)
    jwt.init_app(app)


def register_resources(app):
    api = Api(app)

    api.add_resource(UserListResource, '/users')
    api.add_resource(UserResource, '/users/<string:username>')

    api.add_resource(TokenResource, '/token')

    api.add_resource(RecipeListResource, '/recipes')
    api.add_resource(RecipeResource, '/recipes/<int:recipe_id>')
    api.add_resource(RecipePublishResource, '/recipes/<int:recipe_id>/publish')


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

the results of pip freeze pip freeze的结果

alembic==1.8.1
aniso8601==9.0.1
certifi==2022.6.15
charset-normalizer==2.1.0
click==8.1.3
colorama==0.4.5
commonmark==0.9.1
defusedxml==0.7.1
Flask==2.1.3
Flask-JWT-Extended==3.20.0
Flask-Migrate==3.1.0
Flask-RESTful==0.3.9
Flask-SQLAlchemy==2.5.1
greenlet==1.1.2
httpie==3.2.1
idna==3.3
itsdangerous==2.1.2
Jinja2==3.1.2
Mako==1.2.1
MarkupSafe==2.1.1
multidict==6.0.2
passlib==1.7.4
psycopg2-binary==2.9.3
Pygments==2.12.0
PyJWT==2.4.0
PySocks==1.7.1
pytz==2022.1
requests==2.28.1
requests-toolbelt==0.9.1
rich==12.5.1
six==1.16.0
SQLAlchemy==1.4.39
urllib3==1.26.11
Werkzeug==2.0.0

This is happening because you have a newer version of PyJWT with an older version of flask jwt extended that are incompatible.发生这种情况是因为您有一个较新版本的 PyJWT 与旧版本的 flask jwt 扩展不兼容。 Upgrading flask jwt extended to at least 3.25.0 should fix the issue.将 flask jwt 升级到至少 3.25.0 应该可以解决此问题。 If you upgrade to the 4.xx version of flask jwt extended, make sure to read over the breaking changes here: https://flask-jwt-extended.readthedocs.io/en/stable/v4_upgrade_guide/如果您升级到 flask jwt 扩展版的 4.xx 版本,请务必阅读此处的重大更改: https://flask/jwt-extended.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM