我正在使用Python 3.6在生产模式下的服务器上运行Flask Restful,并遇到需要jwt身份验证的端点,但是我不断收到"NoAuthorizationError Missing Authorization Header"错误。
奇怪的是,使用Postman将相同的请求发送到我Mac上完全相同的Flask应用程序的本地版本,并且它工作正常,没有任何错误。该问题仅发生在实时服务器上,并且所有pip包的版本也完全相同。
更新
我在实时服务器上使用 Gunicorn,当我停止应用程序并使用python run.py
正常运行时,错误消失并返回正确的响应。
我为 jwt 错误设置了以下处理程序,再次,它在我的应用程序的本地版本中被捕获:
- jwt.token_in_blacklist_loader
- jwt.expired_token_loader
- jwt.invalid_token_loader
- jwt.revoked_token_loader
- jwt.needs_fresh_token_loader
- jwt.unauthorized_loader
- jwt.claims_verification_failed_loader
出于测试目的,我不会在请求本身中发送令牌。即使我这样做,错误仍然存在。
这是我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
您是否尝试添加:
"WSGIPassAuthorization On"
在您的 WSGI 虚拟目录配置中? 默认情况下,授权标头不会传递给应用程序,因为它应该由 Web 服务器处理。如果它由您的 python 应用程序处理,您将在生产中的配置代码中需要它。 即使 CORS 没问题,您也需要它,因为它将从您的请求中删除
您看到的错误意味着授权标头未构成烧瓶应用程序。要么它没有被发送,要么在烧瓶到达它之前有什么东西把它剥掉了。
你在使用Apache吗?看起来还有其他关于Apache剥离该标头的报道。也许查看Apache剥离了"授权"标头(特别是"WSGIPAssAuthorization"(,看看是否可以为您解决问题。