I'm trying to add realtime updates on a Django app which has a similar architecture as explained here: http://lincolnloop.com/blog/2012/apr/23/ginger-tech-stack/. Basically, updates are send from Django to Node.js via Redis, then pushed to connected clients with Socket.io. Right now, I can broadcast to every clients connected but in a real case, I need to send data only to clients concerned by an action (e.g.: a user post a message, only his contacts/subscribers receive this message). So I need some kind of authentication on the Node.js side to know who's who. How can this be achieved ?
Here is my solution so far to get the identity of the connected user in socket.io/node.js (if you have better solution, feel free to post):
On Django side:
Patch Django to use json instead of pickle object to store session data:
diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
index 5a637e2..cb4db54 100644
--- a/django/contrib/sessions/backends/base.py
+++ b/django/contrib/sessions/backends/base.py
@@ -2,9 +2,9 @@
import time
from datetime import datetime, timedelta
try:
- import cPickle as pickle
+ import json
except ImportError:
- import pickle
+ import simplejson as json
from django.conf import settings
from django.core.exceptions import SuspiciousOperation
@@ -75,21 +75,21 @@ def _hash(self, value):
return salted_hmac(key_salt, value).hexdigest()
def encode(self, session_dict):
- "Returns the given session dictionary pickled and encoded as a string."
- pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
- hash = self._hash(pickled)
- return base64.encodestring(hash + ":" + pickled)
+ "Returns the given session dictionary as json and encoded as a string."
+ data = json.dumps(session_dict)
+ hash = self._hash(data)
+ return base64.encodestring(hash + ":" + data)
def decode(self, session_data):
encoded_data = base64.decodestring(session_data)
try:
# could produce ValueError if there is no ':'
- hash, pickled = encoded_data.split(':', 1)
- expected_hash = self._hash(pickled)
+ hash, data = encoded_data.split(':', 1)
+ expected_hash = self._hash(data)
if not constant_time_compare(hash, expected_hash):
raise SuspiciousOperation("Session data corrupted")
else:
- return pickle.loads(pickled)
+ return json.loads(data)
except Exception:
# ValueError, SuspiciousOperation, unpickling exceptions. If any of
# these happen, just return an empty dictionary (an empty session).
On Node.js side:
Read the session key from the "sessionid" cookie:
socket.on('connection', function(client) {
...
var cookie_string = client.handshake.headers.cookie;
var parsed_cookies = connect.utils.parseCookie(cookie_string);
var sessionid = parsed_cookies['sessionid'];
...
});
Retrieve & decode the session data from the db corresponding to the sessionid to get the user id.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With