Flask-wtf:csrf_token已从会话中删除,然后才能发布我的表单

时间:2015-05-29 14:55:40

标签: python ajax flask csrf flask-wtforms

我正在使用带有Flask-Security的Flask(特别是关于我的csrf问题的Flask-WTF)以及#34; easy"注册/登录用户的过程(到目前为止还不容易)。我在前端使用BackboneJS,因此我有点破解了使用Flask-WTF的原始方式。实际上,我在/ register上发出一个AJAX GET请求以获取注册页面(由Flask-Security生成),并将生成的HTML放在一个模态中。

render: function () {
            var self = this;
            $.ajax({
                type: 'GET',
                url: Config.constants.serverGateway + "/register"
            }).done(function(result){
                console.log("get register done", result);
                var html = self.template({ config: Config, form: result });
                self.$el.html(html);
            }).fail(function(error){
                console.log("Could not get register token", error);
                var html = this.errorTemplate({ config: Config });
                self.$el.html(html);
            });

            return this;
        }

这样我就生成了csrf,当我发布注册数据时,我会沿着用户数据(电子邮件和密码)发送正确的csrf。

submit: function () {
            console.log("submit");
            var self = this;
            var formData = this.$el.find('form').serialize();
            $.ajax({
                type: 'POST',
                url: Config.constants.serverGateway + "/register",
                data: formData,
                dataType: 'json'
            }).done(function(result){
                self.trigger('close');
            }).fail(function(error){
                console.log("Could not submit register data", error);
            });
        }

在服务器端,我可以调试我的python代码,看看当我请求注册页面时生成的csrf_token已从会话对象中消失,因此导致生成一个新的,当然与我发送的表格不匹配。但是会话仍然是相同的,因为在GET和POST期间_id是相同的。

你可以看到flask_wtf / csrf.py :: generate_csrf()中的代码,当在flask_security / views.py中的:: register函数中创建表单对象时调用该代码

if 'csrf_token' not in session:
    session['csrf_token'] = hashlib.sha1(os.urandom(64)).hexdigest()

导致CSRF TOKEN MISSING错误。

附加信息是我的前端和后端由同一台服务器提供,因为它们有不同的端口号。

最后,当我在前端使用href并在' GET'上显示服务器返回的页面时要求,提交表格效果很好。我只是喜欢以模态显示此注册表单。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

好的,我终于找到了解决问题的方法。我觉得自己像个菜鸟(我是)。

问题在于未通过请求发送到服务器的会话凭据中,因此服务器无法访问会话cookie。 我在以下教程中找到了解决方案:http://backbonetutorials.com/cross-domain-sessions/ 要发送它,我在Backbone路由器初始化函数中添加了以下行:

// Use withCredentials to send the server cookies
// The server must allow this through response headers
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
    options.xhrFields = {
        withCredentials: true
    };
});

这使得所有AJAX请求都包含withCredentials = true。在服务器端,我必须设置Access-Control-Allow-Credentials:true。由于我使用了flask-cors,因此在创建CORS对象时使用[supports_credentials=True][2]

答案 1 :(得分:0)

(我在这里回答,因为我无法发表评论) @junnytony是的我在我的模态中有令牌,我在我的POSt请求中发送它。当我调试Flask应用程序时,我可以看到我通过POST请求发送的toekn,问题是它应该与要验证的会话中的那个进行比较,但是会话中的那个已经消失了,所以烧瓶 - wtf lib生成一个新的,与我发送的文件比较时会导致失败。