2013-07-08 22 views
5

Django'da (1.5) basit bir çok oyunculu kelime oyunu uygulaması üzerinde çalışıyorum. Örnek here'un ardından, istemci bağlantılarını yönetmek için ayrı bir Node.js sunucusu ve Socket.io kullanıyorum.Node.js'den Django'ya CSRF belirtecini geçmek

Sorum aşağı iki kısma ayırır:

  1. öğretici yukarıdaki API görünümü için @csrf_exempt kullanır. POST, istemciden değil, localhost üzerinden Node.js sunucusundan gelmediğinden, bu görünüm için CSRF korumasını kullanmamakla tam olarak nelere maruz kaldım?

  2. Yukarıdakilerden emin olmadığımdan, CSRF korumasını kullanmak istiyorum. CSRF belirtecini Django tarafından sağlanan çerezden çıkarmayı denedim (the docs tarafından önerildiği gibi) ve POST ile birlikte gönderdim, ancak yine de 403 yanıtı alıyorum.

game_server.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 (komut kısım için):

(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')) 

herhangi fikir büyük olacaktır takdir!

cevap

2

Adil bir araştırma ve deneyden sonra sorunu çözdüm.

bulgularım: Bu özellikle durumda

  1. CSRF anlamlı saldırılara Beni ifşa etmez. Teoride, oyunda hile yapmak için bir yol açar, ancak sıfır ödül için bu bir çok zorluk (oturum kimliğinin üretilmesini ve devam eden bir oyunu hedeflemeyi gerektirir). Ancak, sohbet gibi diğer uygulamalarda, bir CSRF güvenlik açığı, birisinin başka bir kullanıcının kimliğine bürünmesine izin verir, ki bu daha önemli bir sorundur. Ve böylece biz daha derine kazıyoruz ...

  2. Sorunu AJAX üstbilgileriyle çözmeye yönelik ilk denemem yanlış oldu. Birincisi, istek AJAX üzerinden gelmiyor. (request.is_ajax(), görünüm içinde False değerini döndürür.) İkinci olarak, Django'dan alınan hata sayfası, başarısızlık nedeni olarak CSRF cookie not set belirtiyor.

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

    uygun 'Cookie' başlık ekleyin ve istek başarılı olur:

Bütün bunlar çözümüne kurar.

İlgili konular