我正在编写一个 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 -