Flask-wtf:csrf_token从会话中删除,然后我可以发布我的表单 [英] Flask-wtf: csrf_token is removed from session before I can POST my form

查看:252
本文介绍了Flask-wtf:csrf_token从会话中删除,然后我可以发布我的表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用Flask-Flask-Security(特别是Flask-WTF关于我的csrf问题)来缓解注册/登录用户的过程(目前并不容易)。我在前端使用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);
});

返回这个;
}

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

  submit:function(){
console .LOG( 提交);
var self = this;
var formData = this。$ el.find('form')。serialize(); $ b $ .ajax({
type:'POST',
url:Config.constants.serverGateway +/ register,
data:formData,
dataType: 'json'
})。done(function(result){
self.trigger('close');
})。fail(function(error){
console。日志(无法提交注册数据,错误);
});



$ b $ p
$ b

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



您可以在flask_wtf / csrf.py :: generate_csrf (),在从flask_security / views.py中创建:: register函数中的表单对象时调用。
$ b $ pre $ 如果'csrf_token '不在会话中:
session ['csrf_token'] = hashlib.sha1(os.urandom(64))。hexdigest()

导致CSRF TOKEN MISSING错误。

另一个信息是,我的前端和后端交付由相同的服务器,因为他们有一个不同的端口号。



最后,当我在前端使用href并显示由服务器在' GET'请求,提交表单运行良好。

感谢您的帮助

解决方案

好吧,我终于想出了解决我的问题的方法。我感觉像一个noob(我是)。

这个问题在于会话证书中没有被发送到服务器的请求,所以服务器coudldn'访问会话cookie。
我在下面的教程中找到了解决方案: http://backbonetutorials.com/cross-domain / b>

  //使用withCredentials来发送服务器的cookie 
//服务器必须通过响应头允许这个
$ .ajaxPrefilter(function(options,originalOptions,jqXHR){
options.xhrFields = {
withCredentials:true
};
});

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


I'm using Flask with Flask-Security (specifically Flask-WTF regarding my csrf issue) to "ease" the process of register/loggin users (not easy so far). I'm using BackboneJS on the front-end, therefore I kind of hacked the original way to use Flask-WTF. Indeed, I make an AJAX GET request on /register to get the register page (generated by Flask-Security) and I put the resulting HTML in a modal.

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;
        }

This way I have the generated csrf, and when I POST the registration data, I send the right csrf along the user data (email and password).

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);
            });
        }

On the server-side, I can debug my python code to see that the csrf_token which has been generated when I requested the register page has disappeared from the session object, therefore leading to the generation of a new one, which of course didn't match the one I send with my form. The session is still the same though, as the _id is the same during the GET and the POST.

You can see the code in flask_wtf/csrf.py::generate_csrf(), which is called when creating the form object in the ::register function from flask_security/views.py

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

It results in a CSRF TOKEN MISSING error.

An additionnal information, is that my front-end and back-end are delivered by the same server, as they have a different port number.

Last, when I use an href on front-end and display the page returned by the server on the 'GET' request, submitting the form works well. I just liked to display this registration form in a modal.

Thanks for your help

解决方案

Okay, I finally figured out the solution to my problem. I feel like a noob (which I am).

The problem lied in the session credentials which were not sent to the server with the requests, so that the server coudldn't access the session cookie. I found the solution in the following tutorial: http://backbonetutorials.com/cross-domain-sessions/ To send it, i added the following lines in my Backbone router initialize function:

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

This makes all AJAX requests include the withCredentials = true. On the server-side, I had to set Access-Control-Allow-Credentials:true. Since I'm using flask-cors, it is done with [supports_credentials=True][2] when creating the CORS object.

这篇关于Flask-wtf:csrf_token从会话中删除,然后我可以发布我的表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆