繁体   English   中英

Flask中AJAX身份验证的CSRF保护

[英]CSRF protection on AJAX authentication in Flask

我想同时使用AJAXify网站上的登录名和注册表。 到目前为止,我一直主要将WTForms用于其内置的CSRF保护,但是对于这个项目,我并不认为这是值得的-额外的抽象层,因此令人沮丧,因为它应该很漂亮简单。

因此,我在Flask的安全性部分遇到了以下片段

@app.before_request
def csrf_protect():
    if request.method == "POST":
        token = session.pop('_csrf_token', None)
        if not token or token != request.form.get('_csrf_token'):
        abort(403)

def generate_csrf_token():
    if '_csrf_token' not in session:
        session['_csrf_token'] = some_random_string()
    return session['_csrf_token']

app.jinja_env.globals['csrf_token'] = generate_csrf_token

我了解此代码背后的思考过程。 实际上,这对我来说完全有意义(我认为)。 我看不出有什么问题。

但这是行不通的。 我对代码所做的唯一更改是将伪函数some_random_string()替换为对os.urandom(24)的调用。 到目前为止,每个请求都有403,因为tokenrequest.form.get('_csrf_token')永远都不相同。 当我打印它们时,这很明显-通常它们是不同的字符串,但偶尔,而且似乎没有根本原因,一个或另一个将是Noneos.urandom(24)输出的截断版本。 显然有些东西不同步,但我不明白它是什么。

您可以在没有所有flask-wtf情况下获得flask-wtf的便利,也无需自己动手:

from flask_wtf.csrf import CsrfProtect

然后在init上:

CsrfProtect(app)

要么:

csrf = CsrfProtect()

def create_app():
    app = Flask(__name__)
    csrf.init_app(app)

该令牌随后将在整个应用范围内可用,包括通过jinja2

<form method="post" action="/">
  <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>

(通过文档

我认为您的问题是os.urandom函数。 此函数的结果可能包含无法在html中正确解析的符号。 因此,当您在html中插入csrf_token并且不进行任何转义时,就会遇到上述问题。

怎么修。 尝试在html中转义csrf_token (请参阅文档),或使用其他方法生成csrf令牌。 例如使用uuid:

import uuid
...

def generate_random_string():
    return str(uuid.uuid4())
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM