【问题标题】:Realtime push/pull with Django/Redis/Node.js使用 Django/Redis/Node.js 进行实时推/拉
【发布时间】:2012-05-13 20:01:03
【问题描述】:

我正在尝试在 Django 应用程序上添加实时更新,该应用程序具有与此处所述类似的架构:http://lincolnloop.com/blog/2012/apr/23/ginger-tech-stack/。基本上,更新通过 Redis 从 Django 发送到 Node.js,然后通过 Socket.io 推送到连接的客户端。现在,我可以向所有连接的客户端广播,但在实际情况下,我只需要向与操作相关的客户端发送数据(例如:用户发布消息,只有他的联系人/订阅者收到此消息)。所以我需要在 Node.js 端进行某种身份验证来知道谁是谁。如何实现?

【问题讨论】:

  • 假设 Django 和 Node 在同一个主机名上,并且您在 Django 中有基于 cookie 的身份验证,因此 Node 可以读取这些 cookie,您可以为 Node 编写一个用于 Django 身份验证的适配器。跨度>
  • 好的,所以我从数据库支持的会话转移到了基于 cookie 的会话,我可以在 Node 端读取 « sessionid » cookie。所以现在我想我必须将this fonction 移植到 Node...
  • 对不起——我不清楚我对基于 cookie 的身份验证的含义:如果你可以从 Node 访问同一个数据库,你应该能够使用 db-backed 会话,我只是说使用会话 ID 的 cookie。任何一种解决方案都应该可以正常工作。是的,node's crypto module 将成为你的朋友。
  • 好吧,在寻找解决方案时,我认为从 Node.js 访问数据库会过于复杂,但它可能比使用 Django 签名的 cookie 容易得多。我要试试这个方法。感谢您指出 ;)
  • 所以现在我可以根据 cookie 的会话 ID 从数据库中检索会话数据。我认为会话数据是base64,但它似乎是python特定的(pickle - 我不熟悉)......有没有办法在节点端解码它?

标签: django node.js redis


【解决方案1】:

到目前为止,这是我在 socket.io/node.js 中获取连接用户身份的解决方案(如果您有更好的解决方案,请随时发布):

在 Django 方面:

  • 修补 Django 以使用 json 而不是 pickle 对象来存储会话数据:

        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).
    

在 Node.js 方面:

  • 从“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'];
        ...
    });
    
  • 从sessionid对应的db中获取session数据并解码,得到用户id。

【讨论】:

  • 既然可以编写自己的会话后端,为什么还要修补 Django?
  • 是的,可能确实更好。所以我尝试扩展 Django db 会话后端:gist.github.com/9ef870e91dc034f60179 但它无法正常工作。不知道出了什么问题...我可以登录,似乎正确创建了 cookie 和数据库条目,但是当我访问 login_required 受保护的视图时,我被重定向到登录页面...
猜你喜欢
  • 1970-01-01
  • 2014-03-22
  • 2020-06-30
  • 2020-01-27
  • 2014-12-12
  • 2013-05-30
  • 2017-04-16
  • 2016-07-21
  • 2020-12-18
相关资源
最近更新 更多