Python 无CSRF的Flask安全令牌登录-几乎达到但不完全达到

Python 无CSRF的Flask安全令牌登录-几乎达到但不完全达到,python,security,authentication,flask,flask-security,Python,Security,Authentication,Flask,Flask Security,我在这方面花了几个小时,我确信我有一个解决方案,对于这里的许多人来说,这将是有用的,因为有许多问题没有答案——如果你能帮助我完善它的话 我有一个flask Web应用程序,它也可以作为我的android应用程序的后端。 我希望在不全局禁用CSRF保护的情况下,通过令牌身份验证保护我的API端点 在所有选项都用完之后,我决定修改Flask安全性以达到我的目的。 这是我的分部 简而言之,我创建了一个额外的视图/api/login,用于呈现一个CSFR被禁用的登录表单(仅该特定表单)。所有其他视图,包

我在这方面花了几个小时,我确信我有一个解决方案,对于这里的许多人来说,这将是有用的,因为有许多问题没有答案——如果你能帮助我完善它的话

我有一个flask Web应用程序,它也可以作为我的android应用程序的后端。 我希望在不全局禁用CSRF保护的情况下,通过令牌身份验证保护我的API端点

在所有选项都用完之后,我决定修改Flask安全性以达到我的目的。 这是我的分部

简而言之,我创建了一个额外的视图/api/login,用于呈现一个CSFR被禁用的登录表单(仅该特定表单)。所有其他视图,包括/login(在我的分支中,我已将其修改为/account/login)保留其CSRF保护。现在,当我使用正确的凭据发布到/api/login时,我得到的令牌没有错误,可以用于任何其他请求。登录API post to/account/Login返回预期的错误,因为视图仍然受到保护

我现在试图实现的是确保浏览器无法访问/api/login视图或接受任何基于会话的身份验证(或者,如果它不返回cookie,而只返回令牌,并且我可以禁用非json帖子的处理,那么它是CSFR安全的吗?)

这就是/api/login视图的外观

@anonymous_user_required
def api_login():
    """View function for api_login view"""

    form_class = _security.api_login_form

    if request.is_json:
        form = form_class(MultiDict(request.get_json()))
    else:
        form = form_class(request.form)

    if form.validate_on_submit():
        login_user(form.user, remember=form.remember.data)
        after_this_request(_commit)

        if not request.is_json:
            return redirect(get_post_login_redirect(form.next.data))

    if request.is_json:
        return _render_json(form, include_auth_token=True)

    return _security.render_template(config_value('LOGIN_USER_TEMPLATE'),
                                     login_user_form=form,
                                     **_ctx('login'))
我目前的想法是只使用查看过程POST方法,替换

else:
        form = form_class(request.form)
(此处返回一个错误)

使浏览器窗体不被处理,并删除窗体渲染


我现在睡觉的时候头都快撑破了,我希望我能醒来时听到一些好消息

我终于做到了这一点

@anonymous_user_required
def api_login():
    """View function for login view"""

    form_class = _security.api_login_form

    if request.is_json:
        form = form_class(MultiDict(request.get_json()))
        if form.validate_on_submit():
            login_user(form.user, remember=form.remember.data)
            after_this_request(_commit)
    else:
        return jsonify(*get_message('INVALID_LOGIN_ATTEMPT'))   

    if request.is_json:
        return _render_json(form, include_auth_token=True)

    return jsonify(*get_message('INVALID_LOGIN_ATTEMPT'))
这确保只处理json帖子,并且站点中的所有其他内容都受到CSRF保护

我可以拿到我的代币(这里我用的是ipython)

在我的正常登录视图上尝试相同操作会返回预期的错误

In [8]: r = requests.post('http://127.0.0.1:5000/account/login', data=
    ...: json.dumps({'email':'me.mine.com', 'password':'goodpw'}), he
    ...: aders={'content-type': 'application/json'})

   In [9]: r.json()
   Out[9]:
   {'meta': {'code': 400},
   'response': {'errors': {'csrf_token': ['The CSRF token is missing.']}}}
我现在计划在某个时候为注册做同样的事情。 如果你想测试这个分支,你可以通过pip安装它

pip install git+https://github.com/mnjenga/flask-security
pip install git+https://github.com/mnjenga/flask-security