Flask中间件在中止401上导致500

qua*_*ack 3 python middleware abort flask

我的Flask应用程序中有一个中间件,该中间件用于验证请求标头中的JSON Web令牌,并正在检查以对其进行验证,以下是我的中间件类:

class AuthMiddleware(object):

    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        path = environ.get('PATH_INFO')
        if path != '/authenticate' or path != '/token':
            token = environ.get('HTTP_X_ACCESS_TOKEN')
            verfied_token = verify_token(token)
            if verfied_token is False:
                abort(401)
            elif verfied_token is True:
                # payload = get_token_payload(token)
                # check_permissions(payload)
                pass

        return self.app(environ, start_response) 
Run Code Online (Sandbox Code Playgroud)

verify_token() 是一个将返回True或False的函数,并且如果返回False,我希望它以错误401终止。但是,它以错误500终止:

class AuthMiddleware(object):

    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        path = environ.get('PATH_INFO')
        if path != '/authenticate' or path != '/token':
            token = environ.get('HTTP_X_ACCESS_TOKEN')
            verfied_token = verify_token(token)
            if verfied_token is False:
                abort(401)
            elif verfied_token is True:
                # payload = get_token_payload(token)
                # check_permissions(payload)
                pass

        return self.app(environ, start_response) 
Run Code Online (Sandbox Code Playgroud)

在我看来,我像应该的那样中止了401,但在这里似乎是个问题。我该怎么办?

dav*_*ism 5

您显示的中间件运行其他代码,然后调用包装的Flask应用程序。但是,abort会引发Flask处理的异常,但不会由WSGI直接处理。由于您还不在Flask应用程序中,因此它无法处理该异常。

一个简单得多的方法是在Flask应用中执行此检查。创建一个before_request处理程序,该处理程序执行与中间件基本相同的操作,不同之处flask.request在于您可以使用而不是自己解析路径和标头。

from flask import request, abort

@app.before_request
def check_auth_token():
    if request.path in ('/authenticate', '/token'):
        return

    token = request.headers.get('X-ACCESS-TOKEN')

    if not verify_token(token):
        abort(401)

    check_permissions(get_token_payload(token))
Run Code Online (Sandbox Code Playgroud)

如果您确实想为此使用WSGI中间件,则需要自己创建响应。方便地,Werkzeug的异常行为类似于WSGI应用程序,因此使用它们非常简单。

from werkzeug.exceptions import Unauthorized

# in place of abort(401) in the middleware
return Unauthorized()(environ, start_response)
Run Code Online (Sandbox Code Playgroud)

您还可以abort通过捕获它引发的异常来使用still(再次是WSGI应用程序)。

from werkzeug.exceptions import abort, HTTPException
# werkzeug.exceptions.abort is the same as flask.abort

try:
    abort(401)
except HTTPException as e:
    return e(environ, start_response)
Run Code Online (Sandbox Code Playgroud)