烧瓶身份验证:RuntimeError:在请求上下文之外工作

时间:2020-05-13 06:17:53

标签: python authentication flask graphql graphene-python

我正在用石墨烯和烧瓶编写GraphQL API。使用不安全的访问,一切都会按预期进行。访问控制表示全部或不表示访问请求是允许还是拒绝,但两者之间什么也没有,也没有细粒度的控制。

我编写了一个身份验证服务来执行此操作,如果API密钥在所有其他情况下均有效或为false,则它将返回true。在将身份验证服务集成到Flask中时,事情变得棘手,我还没有弄清楚如何使用简单的服务在Flask中对GraphQL请求进行身份验证。

this gist

中的完整代码示例

我尝试使用http auth示例,并且使用该模式时我的auth服务可以正常工作。 https://flask-httpauth.readthedocs.io/en/latest/

下面没有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)

但是,石墨烯需要flask add_url格式添加一个视图,在这种情况下,我根本无法使身份验证服务正常工作。具体来说,石墨烯在烧瓶中需要满足以下条件:

@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()

此要点的完整代码:https://gist.github.com/marvin-hansen/430b55e8d304b1db631f4b397a27f827

尝试身份验证服务时,出现以下错误:

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.

说到文档,有很多有关管理上下文的细节,但是很少有关于如何正确获得这种身份验证的。搜索Web有点令人沮丧,因为大多数情况下都处理更复杂的用户身份验证,会话管理和JWT令牌,相对于我的谦虚要求而言,这似乎有些过时了。

在这一点上,尽管任务相对简单,但我不确定如何使我的身份验证服务与石墨烯和烧瓶一起使用,只需提取http-header,验证API密钥,然后让请求继续进行任何有效的API密钥。

任何想法如何解决?

提前谢谢

1 个答案:

答案 0 :(得分:0)

解决方案:Flask中的动态视图需要装饰器才能添加功能。就我而言,我必须编写一个Authenticator装饰器,然后将视图包装在该装饰器中。

# 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))
)
相关问题