社区首页 >问答首页 >将CSRF令牌从Node.js传递给Django

将CSRF令牌从Node.js传递给Django
EN

Stack Overflow用户
提问于 2013-07-08 08:49:50
回答 1查看 2.2K关注 0票数 6

我在Django (1.5)中开发一个简单的多人字游戏应用程序。按照示例here,我使用一个单独的Node.js服务器和Socket.io来管理客户端连接。

我的问题分为两部分:

  1. 上面的教程将@csrf_exempt用于API视图。由于POST不是来自客户端,而是来自本地主机上的Node.js服务器,所以如果不对此视图使用CSRF保护,那么我究竟暴露了什么?
  2. 由于我不确定上述情况,我想使用CSRF保护。我尝试从Django提供的cookie中提取CSRF令牌(正如the docs建议的那样),并将其与帖子一起发送,但我仍然得到了403个响应。

game_server.js:

代码语言:javascript
代码运行次数:0
复制
io.configure(function () {
    io.set('authorization', function (data, accept) {
        if (data.headers.cookie) {
            data.cookie = cookie_reader.parse(data.headers.cookie);
            return accept(null, true);
        }
        return accept('error', false);
    });
    io.set('log level', 1);
});

io.sockets.on('connection', function (socket) {

    socket.on('check_word', function (data) {
        values = querystring.stringify({
            word: data,
            sessionid: socket.handshake.cookie['sessionid']
        });

        var options = {
            host: 'localhost',
            port: 8000,
            path: '/node/check_word',
            method: 'POST',
            headers: {
                'X-CSRFToken': socket.handshake.cookie['csrftoken'],
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': values.length
            }
        };

        var req = http.request(options, function (res) {
            res.setEncoding('utf8');

            res.on('data', function (message) {
                if (message) {
                    console.log(message);
                }
            });
        });

        req.write(values);
        req.end();
    });
});

game.html (只有脚本部分):

代码语言:javascript
代码运行次数:0
复制
(function ($) {
  var socket = io.connect('localhost', { port: 4000 });

  socket.on('connect', function () {
    console.log("connected");
  });

  word_el = $('#word-input');

  word_el.keypress(function (event) {
    if (event.keyCode === 13) {
      // Enter key pressed
      var word = word_el.attr('value');
      if (word) {
        socket.emit('check_word', word, function (data) {
          console.log(data);
        });
      }

      word_el.attr('value', '');
    }
  });
})(jQuery);

views.py:

代码语言:javascript
代码运行次数:0
复制
@ensure_csrf_cookie
def check_word(request):
    return HttpResponse("MATCH:" + request.POST.get('word'))

任何洞察力都将不胜感激!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-10 04:56:08

经过大量的研究和实验,我解决了这个问题。

我的发现:

  1. 在这种情况下,CSRF不会让我受到任何有意义的攻击。从理论上讲,它为游戏中的作弊开辟了一条途径,但这是一个很大的困难(需要制作会话id,并以当前正在进行的游戏为目标),以获得零奖励。但是,在其他应用程序(如chat )中,CSRF漏洞允许某人冒充另一个用户,这是一个更重要的问题。所以我们挖得更深。
  2. 我最初试图通过AJAX头来解决这个问题是个错误。首先,请求实际上并不是通过AJAX来实现的。(request.is_ajax()在视图中返回False。)其次,从Django收到的错误页面引用了CSRF cookie not set作为失败的原因。

所有这些都符合解决方案:

代码语言:javascript
代码运行次数:0
复制
var options = {
    // snip...
    headers: {
        'Cookie': 'csrftoken=' + socket.handshake.cookie['csrftoken'],
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': values.length
    }
};

添加适当的'Cookie'头,请求就会成功。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17531978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文