Flask-Security CSRF 令牌

Posted

技术标签:

【中文标题】Flask-Security CSRF 令牌【英文标题】:Flask-Security CSRF token 【发布时间】:2013-08-28 11:17:20 【问题描述】:

我有一个用作 REST API 后端的烧瓶应用程序。我想为后端实现基于令牌的身份验证,但为了做到这一点,我需要检索用户令牌。 Flask-Security 文档明确指出,要检索令牌,需要执行 HTTP POST,其中将身份验证详细信息作为 JSON 数据发送到身份验证端点。不幸的是,我不明白如何检索执行此类请求所需的 CSRF 令牌。

如果我使用扩展提供的登录页面/模板,CSRF 令牌将在表单的隐藏字段中传递给客户端。问题是:

如何在不访问和解析登录页面的情况下检索 CSRF 令牌,例如从使用 $http 方法的 angularJS 应用程序或移动应用程序?

显然我可以避免使用 Flask-Security 并自己实现这些部分,但我对 webapps 相对缺乏经验,我觉得我可能以错误的方式处理这个问题。

【问题讨论】:

你最后是怎么做到的? 我最终自己实现了安全层。对不起,我没有更好的答案给你。 请注意,没有将令牌存储在 angularjs 中的安全方法,请参见例如here。安全选项是让服务器将令牌存储在仅限 http 的 cookie 中 + 启用 CSRF 保护。如果您只需要与 angularjs 交谈,那么您也可以使用会话(+ anti-CSRF)。 【参考方案1】:

我有一个类似的用例,并通过遵循 Flask-WTF 文档中的这个示例来解决它:https://flask-wtf.readthedocs.org/en/latest/csrf.html#ajax

因此,通过 CSRF 通过CsrfProtect(app) 保护应用程序,csrf_token() 在所有模板中都可用。然后你可以很容易地通过脚本标签使它可用:

<script type="text/javascript">
    var csrftoken = " csrf_token() "
</script>

现在将令牌添加到 Flask-Security /login 端点的发布数据中。

【讨论】:

感谢您的回答,但我最终实现了自己的用户管理解决方案。此外,这仅在您使用 Flask 应用程序提供页面并使用 Jinja 呈现模板时才有效。如果您仅将 Flask 应用程序用于后端(REST API)并且使用其他方法为前端提供服务,则您必须提供 API 端点来检索令牌并将其呈现在 json 响应中。我不确定这会如何工作,我可能会尝试一下。【参考方案2】:

嗯,有一个简单的方法。 Visit。可以将配置项 WTF_CSRF_ENABLED 设置为 False 以禁用 csrf。然后一切如你所愿。

【讨论】:

这解决了我的问题,谢谢。它可能被否决了,因为它禁用了安全功能。但是如果 REST 服务器只进行令牌认证而不是基于 cookie 的认证,那么 CSRF 令牌是多余的。 (我欢迎所有的cmets!) 非常感谢!这个对我有用。使用邮递员烧瓶应用程序测试【参考方案3】:

我还没有测试过它是否有效,但通过简单检查source code,您似乎必须向登录 URL 发送一个 GET 请求,并将内容类型设置为application/json。 Flask-Security 使用包含令牌的 JSON 版本的登录表单响应此请求。获得令牌后,您可以发送 POST 请求。

【讨论】:

感谢您走上正确的道路。除了发出 GET 请求之外,我还必须在请求中传递一些 json 数据,否则 Flask 中的“request.json”为空,并且不会触发“_render_json”方法。不幸的是,尽管这会导致您链接的源代码的第 45 行出现错误,因为该表单没有用户属性。但是简单地看一下代码,我认为应该在验证期间设置用户属性,但这个请求不会发生。我得继续挖掘。再次感谢 好的,我发现了错误。 Flask-WTF 的 'validate_on_submit' 方法首先检查 'is_submitted' 对于 GET 请求是否为假。这可以防止调用“验证”方法和分配表单中的“用户”属性。但是,手动调用“验证”方法会产生“缺少 CSRF 令牌”错误,我们又回到了起点。【参考方案4】:

昨晚我为这个问题奋斗了好几个小时。以下是最终为我工作的内容:

当我创建我的应用实例时:

app = Flask(__name__)
app.config.from_object(config_by_name[config_name])

# Create database connection object
app.db = db
app.db.init_app(app)

CsrfProtect(app)

在我的 /login HTML 中:

<meta name="csrf-token" content=" csrf_token() ">

来自邮递员:

这是我尝试过的另一种选择,也许这会更成功?这与烧瓶安全示例应用程序给出的回复基本相同:

【讨论】:

【参考方案5】:

[写一个答案,因为我没有足够的声誉来发表评论]

我遇到了与 Jacopo 完全相同的问题,因为 request.json 是空的,因此不会触发 get_auth_token()。

顺便说一句 - Flask Security documentation 说:

基于令牌的身份验证通过执行 HTTP POST 来检索用户身份验证令牌来启用,其中身份验证详细信息作为针对身份验证端点的 JSON 数据。

所以我尝试了 POST,而不是 GET(空 request.json 的问题仍然相同) 我用 json 数据调用 /login 为:

"email": "test@example.com", "password": "test123"

并使用 Google Chrome 中的 Postman 客户端发送请求。

然而,request.json 是空的 :(

编辑:我能够使用 python 的请求模块继续前进。详情here

【讨论】:

嗨 Mandar,我希望你解决了这个问题,但我刚刚发布了一个可能有帮助的答案:***.com/a/27926284/992509 您在博文中给出的关于 startquestion(如何在 flask-security 上使用 json 登录时实现 csrf 令牌)的答案本质上是:在 flask-security 的配置中禁用 csrf 身份验证。这是要保存吗?根据这个article,只要你不使用cookies:“CSRF:既然你不依赖cookies,你不需要保护跨站点请求......”但它真的就像另存为使用 csrf 令牌?

以上是关于Flask-Security CSRF 令牌的主要内容,如果未能解决你的问题,请参考以下文章

快速 CSRF 令牌验证

在测试中获取 CSRF 令牌,“CSRF 令牌无效” - 功能性 ajax 测试

api 端点未在 Sanctum 上进行 CSRF 令牌验证 - CSRF 令牌不匹配

过滤 CSRF 令牌以防止 CSRF

csrf 令牌会在 laravel 中的每个请求上自动重新生成,这会导致生产服务器上的 csrf 令牌不匹配

一个令牌与多个令牌以防止 CSRF 攻击