2

我正在编写一个 Flask 后端来通过 JWT 提供具有身份验证的 RESTful API。

我正在使用 Flask-Admin 作为管理员,为了使用单一身份验证方法,我也想使用 JWT 身份验证。

我向 Flask-Admin 添加了一个简单的登录表单,用于在 cookie 中设置 JWT 令牌。

create_form在my 的方法中的请求中找到并正确解码了 JWT 令牌sqla.ModelView,但是在发布表单时(通过单击save我的创建表单的按钮,我收到 401 错误:“在 headers 中缺少 CSRF 令牌

有人可以帮忙吗?

登录路径

@bp_api.route('/api/user/login', methods=('POST',))
def login():

    data = request.json

    web = request.args.get('web', 0, type=int)


    user = User.query.filter(User.username==data['username']).first()

    if not user:
        return jsonify({'msg': 'User {} doesn\'t exist'.format(data['username'])}), 400

    if not user.confirmed_on:
        return jsonify({'msg': f'{user.email} not confirmed'}), 400

    if check_password_hash(user.password, data['password']):
        access_token = create_access_token(identity = data['username'], fresh=True)
        refresh_token = create_refresh_token(identity = data['username'])
        if web:
            resp = jsonify({'username': f'{user.username}'})
            set_access_cookies(resp, access_token)
            set_refresh_cookies(resp, refresh_token)
        else:
            resp = jsonify({'msg':f'Logged as {user.username}',
                'access_token': access_token, 'refresh_token': refresh_token}
            )
        return resp, 200

    else:
        return jsonify({'msg': 'Invalid password.'}), 401

Flask-Admin 视图

from flask_admin.base import BaseView
from flask_admin.contrib import sqla

from flask_jwt_extended import (
    get_current_user,
    get_jwt_identity,
    jwt_required,
    verify_jwt_in_request,
    verify_jwt_refresh_token_in_request,
    create_access_token,
    set_access_cookies,
    unset_jwt_cookies,
)
from flask_jwt_extended.exceptions import NoAuthorizationError
from jwt import ExpiredSignatureError



class PhaunosBaseView(BaseView):

    def render(self, template, **kwargs):
    try:
        verify_jwt_in_request()
        self._template_args['current_user'] = get_current_user()
        current_app.logger.info("Access token ok for user {}".format(get_current_user()))
        resp = make_response(super(PhaunosBaseView, self).render(template, **kwargs))

    except ExpiredSignatureError:
        # if the access token has expired, create new non-fresh token
        current_app.logger.info("Access token has expired.")
        try:
            verify_jwt_refresh_token_in_request()
            self._template_args['current_user'] = get_current_user()
            access_token = create_access_token(identity=get_jwt_identity(), fresh=False)
            resp = make_response(super(PhaunosBaseView, self).render(template, **kwargs))
            set_access_cookies(resp, access_token)
        except ExpiredSignatureError:
            # if the refresh token has expired, user must login again
            current_app.logger.info("Refresh token has expired")
            resp = make_response(super(PhaunosBaseView, self).render(template, **kwargs))
            unset_jwt_cookies(resp)
    except NoAuthorizationError:
        current_app.logger.info("No authorization token.")
        resp = make_response(super(PhaunosBaseView, self).render(template, **kwargs))
    return resp


class PhaunosModelView(PhaunosBaseView, sqla.ModelView):
    pass    


class ProjectAdminView(PhaunosModelView):   

    def create_form(self, obj=None):
        current_app.logger.info("In create_form")
        form = super(ProjectAdminView, self).create_form(obj)
        current_app.logger.info(request.headers)
        verify_jwt_in_request()
        return form

    def on_model_change(self, form, model, is_created):
        current_app.logger.info("In on_model_change")
        current_app.logger.info(id(request))
        current_app.logger.info(request.headers)
        verify_jwt_in_request()
        # then set get_current_user() to some model attribute

日志

[2019-03-28 18:20:27,311] INFO in views: In create_form
[2019-03-28 18:20:27,312] INFO in views: 140045316455232
[2019-03-28 18:20:27,312] INFO in views: Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1:5000/admin/admin_project/
Connection: keep-alive
Cookie: session_id=0c89eb809ae01aa65aa58bbc45faf79b31af32db; access_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTM3OTcxOTYsIm5iZiI6MTU1Mzc5NzE5NiwianRpIjoiMWU0ZTA3YzItMjJjOC00NTFhLWJkNjAtYjllNzZmNWYzMTYyIiwiZXhwIjoxNTUzNzk3Mzc2LCJpZGVudGl0eSI6ImR1bW15X3VzZXI0MiIsImZyZXNoIjp0cnVlLCJ0eXBlIjoiYWNjZXNzIiwiY3NyZiI6IjkwZTY5ZjM1LWQwNDctNDM0NC1hOWVlLTg2NDM4OWFiNzM4OCJ9.0p1CBGxpUzLgIR369I1yP-FTRel4-fhAIeL084YV_O0; csrf_access_token=90e69f35-d047-4344-a9ee-864389ab7388; refresh_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTM3OTcxOTYsIm5iZiI6MTU1Mzc5NzE5NiwianRpIjoiODI0MGJkODItYjg0NC00MjI5LWFiN2MtZTRhN2IwYzgxYzYzIiwiZXhwIjoxNTUzNzk3NTU2LCJpZGVudGl0eSI6ImR1bW15X3VzZXI0MiIsInR5cGUiOiJyZWZyZXNoIiwiY3NyZiI6Ijg1M2FiYzk0LWU2YjctNGZkZi05YzRhLTczNDMxZWE4NGRlOCJ9.CcHzlWsT9kBURZ1FaeCjG8du7FGXLD-fm5-HF0sBdJ8; csrf_refresh_token=853abc94-e6b7-4fdf-9c4a-73431ea84de8
Upgrade-Insecure-Requests: 1


[2019-03-28 18:20:27,316] INFO in views: Access token ok for user dummy_user42
172.23.0.1 - - [28/Mar/2019 18:20:27] "GET /admin/admin_project/new/?url=%2Fadmin%2Fadmin_project%2F HTTP/1.1" 200 -
[2019-03-28 18:21:11,496] INFO in views: In create_form
[2019-03-28 18:21:11,496] INFO in views: 140045316455232
[2019-03-28 18:21:11,496] INFO in views: Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1:5000/admin/admin_project/new/?url=%2Fadmin%2Fadmin_project%2F
Content-Type: multipart/form-data; boundary=---------------------------209115246111667105161673380
Content-Length: 857
Connection: keep-alive
Cookie: session_id=0c89eb809ae01aa65aa58bbc45faf79b31af32db; access_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTM3OTcxOTYsIm5iZiI6MTU1Mzc5NzE5NiwianRpIjoiMWU0ZTA3YzItMjJjOC00NTFhLWJkNjAtYjllNzZmNWYzMTYyIiwiZXhwIjoxNTUzNzk3Mzc2LCJpZGVudGl0eSI6ImR1bW15X3VzZXI0MiIsImZyZXNoIjp0cnVlLCJ0eXBlIjoiYWNjZXNzIiwiY3NyZiI6IjkwZTY5ZjM1LWQwNDctNDM0NC1hOWVlLTg2NDM4OWFiNzM4OCJ9.0p1CBGxpUzLgIR369I1yP-FTRel4-fhAIeL084YV_O0; csrf_access_token=90e69f35-d047-4344-a9ee-864389ab7388; refresh_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NTM3OTcxOTYsIm5iZiI6MTU1Mzc5NzE5NiwianRpIjoiODI0MGJkODItYjg0NC00MjI5LWFiN2MtZTRhN2IwYzgxYzYzIiwiZXhwIjoxNTUzNzk3NTU2LCJpZGVudGl0eSI6ImR1bW15X3VzZXI0MiIsInR5cGUiOiJyZWZyZXNoIiwiY3NyZiI6Ijg1M2FiYzk0LWU2YjctNGZkZi05YzRhLTczNDMxZWE4NGRlOCJ9.CcHzlWsT9kBURZ1FaeCjG8du7FGXLD-fm5-HF0sBdJ8; csrf_refresh_token=853abc94-e6b7-4fdf-9c4a-73431ea84de8
Upgrade-Insecure-Requests: 1


172.23.0.1 - - [28/Mar/2019 18:21:11] "POST /admin/admin_project/new/?url=%2Fadmin%2Fadmin_project%2F HTTP/1.1" 401 -
4

1 回答 1

-1

我在帖子中遇到了同样的问题。在获取时我没有问题。

我添加到我的配置中

    app.config['JWT_COOKIE_CSRF_PROTECT'] = False

它工作..希望这对某人有帮助!

于 2021-11-03T13:11:38.803 回答