如何在 Flask 中实现令牌认证?

Posted

技术标签:

【中文标题】如何在 Flask 中实现令牌认证?【英文标题】:How do you implement token authentication in Flask? 【发布时间】:2015-12-07 05:41:27 【问题描述】:

我正在尝试允许用户使用他们的帐户从单独的 Web 服务登录到我的 Flask 应用程序。我可以联系此 Web 服务的 api 并接收安全令牌。如何使用此令牌对用户进行身份验证,以便他们可以访问受限视图?

我不需要将用户保存到我自己的数据库中。我只想对它们进行身份验证以进行会话。我相信这可以使用 Flask-Security 和 @auth_token_required 装饰器来完成,但文档不是很详细,我不确定如何实现。

编辑:

这是一个代码示例:

@main.route("/login", methods=["GET", "POST"])
def login():

    payload = "User": "john", "Password": "password123"
    url = "http://webserviceexample/api/login"
    headers = 'content-type': 'application/json')

    #login to web service
    r = requests.post(url, headers=headers, json=payload)
    response = r.json()

    if (r.status_code is 200):
        token = response['user']['authentication_token']

        # allow user into protected view

    return render_template("login.html", form=form)


@main.route('/protected')
@auth_token_required
def protected():
    return render_template('protected.html')

【问题讨论】:

你需要用token存储用户;并针对服务确认令牌的有效性。否则,您每次启动时都必须针对第 3 方服务对访问者进行身份验证。 每次是指每个会话?如果是这样,那很好,他们必须再次进行身份验证。这会是一个问题吗? 【参考方案1】:

嘿,Amedrikaner!

看起来您的用例很简单,我们可以自己实现。在下面的代码中,我会将您的令牌存储在用户会话中并签入新的包装器。让我们从制作我们自己的包装器开始吧,我通常只是将它们放在一个 wrappers.py 文件中,但你可以将它放在你喜欢的地方。

def require_api_token(func):
    @wraps(func)
    def check_token(*args, **kwargs):
        # Check to see if it's in their session
        if 'api_session_token' not in session:
            # If it isn't return our access denied message (you can also return a redirect or render_template)
            return Response("Access denied")

        # Otherwise just send them where they wanted to go
        return func(*args, **kwargs)

    return check_token

酷!

现在我们已经实现了包装器,我们可以将它们的令牌保存到会话中。超级简单。让我们修改你的函数...

@main.route("/login", methods=["GET", "POST"])
def login():

    payload = "User": "john", "Password": "password123"
    url = "http://webserviceexample/api/login"
    headers = 'content-type': 'application/json')

    #login to web service
    r = requests.post(url, headers=headers, json=payload)
    response = r.json()

    if (r.status_code is 200):
        token = response['user']['authentication_token']

        # Move the import to the top of your file!
        from flask import session

        # Put it in the session
        session['api_session_token'] = token

        # allow user into protected view

    return render_template("login.html", form=form)

现在您可以使用 @require_api_token 包装器检查受保护的视图,如下所示...

@main.route('/super_secret')
@require_api_token
def super_secret():
    return "Sssshhh, this is a secret"

编辑 哇!我忘了提到你需要在你的应用配置中设置你的 SECRET_KEY。

只需一个带有 SECRET_KEY="SOME_RANDOM_STRING" 的 config.py 文件即可。然后加载它...

main.config.from_object(config)

【讨论】:

我们只需要这两个元素还是不应该有另一个函数来根据数据库验证用户凭据? @EvanBurbidge 抱歉回复晚了。此实现专门用于针对其他地方的外部 API 对用户进行身份验证。最喜欢遵循标准用户登录流程的人,请查看此链接以获取更多信息flask-login.readthedocs.io/en/latest @FBoucaut 感谢您再次联系!我实际上开始使用节点并使用基于令牌的身份验证制作了一个非常好的用户登录/注册/注销包!决定一直保留所有的JS :) 我有兴趣构建与此类似的身份验证。任何人都可以提供一些信息来说明身份验证 API 如何才能使其工作。或者可以提供一个资源链接来解释如何构建这样的 API。谢谢! @MarcB。这可以帮助你realpython.com/token-based-authentication-with-flask

以上是关于如何在 Flask 中实现令牌认证?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flask 中实现登录所需的装饰器

如何在 Spring Boot 中实现刷新令牌

如何在Flask中实现可视化?

如何在ios中实现刷新令牌

如何在 Flask 中实现基于角色的访问控制?

如何在 Flask 框架中实现服务器推送?