我正在使用 Django (1.5) 开发一个简单的多人文字游戏应用程序。按照示例 here ,我使用单独的 Node.js 服务器和 Socket.io 来管理客户端连接。
我的问题分为两部分:
上面的教程使用
@csrf_exempt
作为 API View 。由于 POST 不是来自客户端,而是来自本地主机上的 Node.js 服务器,如果不对此 View 使用 CSRF 保护,我到底会暴露什么?由于我不确定以上内容,我想使用 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'))
任何见解将不胜感激!
最佳答案
经过大量的研究和实验,我已经解决了这个问题。
我的发现:
在这个特殊案例中,CSRF 不会让我暴露于任何有意义的攻击。从理论上讲,它为游戏中的作弊开辟了一条途径,但这对于零奖励来说难度很大(需要伪造 session ID 并针对当前正在进行的游戏)。然而,在聊天等其他应用程序中,这里的 CSRF 漏洞允许某人冒充另一个用户,这是一个更重要的问题。所以我们深入挖掘......
我最初尝试通过 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/