Flask认证。RuntimeError: 在请求上下文之外工作

问题描述 投票:0回答:1

我正在用石墨烯&flask写一个GraphQL API。在不安全访问的情况下,一切都能如期进行。访问控制意味着全部或全部不允许,所以要么允许或拒绝传入的请求,但中间没有任何东西,也没有细粒度的控制。

我写了一个认证服务,正是这样做的,如果一个API密钥是有效的,它就返回true,而在所有其他情况下则返回false。当涉及到将该认证服务集成到Flask中时,事情变得很棘手,我还没有弄清楚如何在Flask中使用简单的服务来认证GraphQL请求。

完整的代码样本在 此要旨

我尝试了http auth的例子,当使用该模式时,我的auth服务工作。https:/flask-httpauth.readthedocs.ioenlatest。

下面的代码示例在没有GraphQL API的情况下,可以按照预期工作,测试我写的auth服务,而且auth服务实际上通过了所有单元测试。

@auth.verify_token
def verify_token(token): 
b = authenticate_token(token) # wrapper to simple auth service 
if b:
    return "OK"

@app.route('/')
@auth.login_required
def index():
  return "Hello, {}!".format(auth.current_user())


if __name__ == '__main__':
    app.run(port=int("7000"), debug=True)

然而,graphene需要flask add_url格式来添加一个视图,在这种情况下,我根本无法让我的认证服务工作。具体来说,graphene在flask中需要以下内容。

@auth.verify_token
def verify_token(token):
    auth = authenticate_token(token)

if auth:
    return "OK"

app.add_url_rule(
'/',
view_func=GraphQLView.as_view('graphql', schema=schema, 
graphiql=True)
)

@auth.login_required # this doesn't work 
def main():
   app.run(port=int("4000"), debug=True)


if __name__ == '__main__':
    main()

完整的代码在这个gist里 https:/gist.github.commarvin-hansen430b55e8d304b1db631f4b397a27f827。

当我尝试认证服务时,得到以下错误。

RuntimeError: Working outside of request context.

This typically means that you attempted to use 
functionality that needed
an active HTTP request.  Consult the documentation on 
testing for information about how to avoid this problem.

说到文档,有很多关于管理上下文的细节,但关于如何正确地进行这种认证的内容却很少。在网上搜索有点沮丧,因为大多数案例处理的是更复杂的用户认证、会话管理&JWT令牌,相对于我的卑微要求来说,这似乎是矫枉过正。

在这一点上,我不知道如何使我的身份验证服务与graphene &flask一起工作,虽然任务相对简单,只是提取http-header,验证API密钥,并让请求继续任何有效的API密钥。

有什么办法可以解决这个问题吗?

先谢谢你

python authentication flask graphql graphene-python
1个回答
0
投票

解决方案:Flask中的动态视图需要一个装饰器来添加功能。在我的案例中,我不得不编写一个身份验证器装饰器,然后将视图包裹在装饰器中。

# The decorator authentication function

def require_apikey(view_function):

@wraps(view_function)
   # the new, post-decoration function. Note *args and **kwargs here.
   def decorated_function(*args, **kwargs):
       # headers.get checks if a key is present
       if request.headers.get('API_KEY') and authenticate_token(request.headers['API_KEY']):
        return view_function(*args, **kwargs)
       else:
           abort(401)

       return decorated_function


app.add_url_rule(
    '/',
    view_func=require_apikey(GraphQLView.as_view('graphql', schema=schema, graphiql=True))
)
© www.soinside.com 2019 - 2024. All rights reserved.