Я запускаю Flask Restful на сервере в режиме производства с использованием Python 3.6 и нажимаю конечную точку, для которой требуется jwt auth, но я продолжаю получать сообщение об ошибке "NoAuthorizationErrorEnror Missing Authorization Header".
Странная часть состоит в том, что тот же самый запрос отправляется с помощью Postman в локальную версию того же самого приложения Flask на моем mac, и он отлично работает без ошибок. Проблема возникает только на реальном сервере, и все пакеты pip также являются одной и той же версией.
ОБНОВЛЕНИЕ Я использую Gunicorn на реальном сервере, и когда я останавливаю приложение и запускаю нормально, используя python run.py
ошибка исчезает и возвращает правильный ответ.
У меня есть следующие обработчики, установленные для ошибок jwt и снова, они попадают в локальную версию моего приложения:
В целях тестирования я не отправляю токен в самом запросе. Даже если я это сделаю, ошибка все еще сохраняется.
Вот ответ локально на моем mac:
{
"errors": {
"application": "Missing Authorization Header",
"validation": null
},
"http_status": 401,
"message": "There was a problem authenticating your token.",
"status": 0,
"time": 20
}
Вот ответ на реальном сервере:
Aug 29 17:15:15 [5168]: return self.dispatch_request(*args, **kwargs)
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_restful/__init__.py", line 595, in dispatch_request
Aug 29 17:15:15 [5168]: resp = meth(*args, **kwargs)
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 102, in wrapper
Aug 29 17:15:15 [5168]: verify_jwt_in_request()
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 31, in verify_jwt_in_request
Aug 29 17:15:15 [5168]: jwt_data = _decode_jwt_from_request(request_type='access')
Aug 29 17:15:15 [5168]: File "/home/domain.com/apps/core-api/env/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 284, in _decode_jwt_from_request
Aug 29 17:15:15 [5168]: raise NoAuthorizationError(errors[0])
Aug 29 17:15:15 [5168]: flask_jwt_extended.exceptions.NoAuthorizationError: Missing Authorization Header
Я пытался отслеживать эту проблему здесь, но не добился успеха.
Для всех, кто сталкивается с этой ошибкой, на самом деле проблема с Flask Restful сама и как она обрабатывает ошибки.
Решение №1
Первое решение, которое действительно сработало для меня, заключалось в распространении исключений... что означает, что исключения обрабатываются повторно, а не обрабатываются обработчиками ошибок приложения. Однако, в соответствии с этим, это не отличное решение, поскольку оно переопределяет функции обработчика ошибок Flask: app.handle_user_exception
и app.handle_exception
.
Таким образом, вы должны установить PROPAGATE_EXCEPTIONS
в своей конфигурации приложения:
app.config['PROPAGATE_EXCEPTIONS'] = True
Решение №2
Окончательное решение, которое я собираюсь сделать, - это улучшить обработчик ошибок Flask Api, основанный на недавнем предложении, найденном здесь.
from flask import Flask
from flask_restful import Api
class CustomApi(Api):
def handle_error(self, e):
for val in current_app.error_handler_spec.values():
for handler in val.values():
registered_error_handlers = list(filter(lambda x: isinstance(e, x), handler.keys()))
if len(registered_error_handlers) > 0:
raise e
return super().handle_error(e)
app = Flask(__name__)
api = CustomApi(app, prefix='/api/v2') # same params can be passed here
Ошибка, которую вы видите, означает, что заголовок авторизации не делает это до приложения в колбе. Либо он не отправляется, либо что-то лишает его, прежде чем колба сможет добраться до него.
Вы используете Apache? Похоже, были и другие сообщения об отключении Apache из этого заголовка. Возможно, проверьте, что Apache отключает заголовок "Авторизация" (в частности, "WSGIPAssAuthorization") и выясняет, устраняет ли это проблему для вас.
Вы пытались добавить:
"WSGIPassAuthorization On"
внутри вашей конфигурации виртуального каталога wsgi? Заголовок авторизации по умолчанию не передается приложению, поскольку он должен обрабатываться веб-сервером. Если это дескриптор вашего приложения python, вам понадобится его код конфигурации. Даже если CORS в порядке, вам это понадобится, поскольку он будет удален из вашего запроса