javascript - 将 CSRF token 从 Node.js 传递到 Django

标签 javascript django socket.io csrf

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

我的问题分为两部分:

  1. 上面的教程使用 @csrf_exempt 作为 API View 。由于 POST 不是来自客户端,而是来自本地主机上的 Node.js 服务器,如果不对此 View 使用 CSRF 保护,我到底会暴露什么?

  2. 由于我不确定以上内容,我想使用 CSRF 保护。我已尝试从 Django 提供的 cookie 中提取 CSRF token (如 the docs 所建议)并将其与 POST 一起发送,但我仍然收到 403 响应。

游戏服务器.js:

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(仅脚本部分):

(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:

@ensure_csrf_cookie
def check_word(request):
    return HttpResponse("MATCH:" + request.POST.get('word'))

任何见解将不胜感激!

最佳答案

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

我的发现:

  1. 在这个特殊案例中,CSRF 不会让我暴露于任何有意义的攻击。从理论上讲,它为游戏中的作弊开辟了一条途径,但这对于零奖励来说难度很大(需要伪造 session ID 并针对当前正在进行的游戏)。然而,在聊天等其他应用程序中,这里的 CSRF 漏洞允许某人冒充另一个用户,这是一个更重要的问题。所以我们深入挖掘......

  2. 我最初尝试通过 AJAX header 解决问题是一个错误。一方面,请求实际上并不是通过 AJAX 发送的。 (request.is_ajax() 在 View 中返回 False。)其次,从 Django 收到的错误页面引用 CSRF cookie not set 作为失败的原因。

所有这些都构成了解决方案:

var options = {
    // snip...
    headers: {
        'Cookie': 'csrftoken=' + socket.handshake.cookie['csrftoken'],
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': values.length
    }
};

添加适当的 'Cookie' header ,请求成功。

关于javascript - 将 CSRF token 从 Node.js 传递到 Django,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17531978/

相关文章:

python - 验证 django 内联表单集

javascript - 连接后忽略服务器端的 socket.emit?

javascript - Socket.io 和 Async 不返回值

javascript - 将 Javascript 代码发送到浏览器

javascript - Jquery 自动完成不起作用

django - 使用 Queryset API 按组计算总和

python - IOError - 解码器 jpeg 不可用 - 即使在安装 libjpeg-dev n PIL 之后也是如此

javascript - 通过 WebSockets 发送位置更新的正确方法是什么?

javascript - Node js URL解析

javascript - 网格中的最后一列需要自定义标题