关于auth和session如何在Python / Django中工作有点困惑

时间:2011-08-05 01:44:47

标签: python django session authentication login

我正在使用现有的数据库作为我最新的Django项目,所以除非我改变我的模型或Django auth代码,否则将两者合并起来相当困难。

我打算只编写自己的身份验证应用程序,而不是搞乱现有的身份验证后端。

无论如何,我之前的所有身份验证应用程序都是用PHP编写的,基本上我只是将所有内容都放在会话变量中并在每个页面上验证它们......这就是我有点困惑的事情。看来,当用户通过身份验证/登录时,整个用户都会被添加到会话中,但我无法确定其发生的位置或方式。

在默认的Django登录功能中,它将用户分配给request.user ...这是以某种方式保存为会话变量还是只是传递到下一个视图?如果它只是被传递到下一个视图,未来的请求如何进行身份验证而不需要进一步的登录请求?

默认的Django auth登录位于以下..

def login(request, user):
    """
    Persist a user id and a backend in the request. This way a user doesn't
    have to reauthenticate on every request.
    """
    if user is None:
        user = request.user
    # TODO: It would be nice to support different login methods, like signed cookies.
    if SESSION_KEY in request.session:
        if request.session[SESSION_KEY] != user.id:
            # To avoid reusing another user's session, create a new, empty
            # session if the existing session corresponds to a different
            # authenticated user.
            request.session.flush()
    else:
        request.session.cycle_key()
    request.session[SESSION_KEY] = user.id
    request.session[BACKEND_SESSION_KEY] = user.backend
    if hasattr(request, 'user'):
        request.user = user
    user_logged_in.send(sender=user.__class__, request=request, user=user)

我也尝试跟随django.dispatch.dispatcher.send中的user_logged_in.send(),但我不完全确定它应该做什么。

def send(self, sender, **named):
    """
    Send signal from sender to all connected receivers.

    If any receiver raises an error, the error propagates back through send,
    terminating the dispatch loop, so it is quite possible to not have all
    receivers called if a raises an error.

    Arguments:

        sender
            The sender of the signal Either a specific object or None.

        named
            Named arguments which will be passed to receivers.

    Returns a list of tuple pairs [(receiver, response), ... ].
    """
    responses = []
    if not self.receivers:
        return responses

    for receiver in self._live_receivers(_make_id(sender)):
        response = receiver(signal=self, sender=sender, **named)
        responses.append((receiver, response))
    return responses

基本上我正在寻找的是有人解释一种有效的方法来保存Python中不依赖于Django框架的用户会话数据。 Django身份验证的一点点运行也很不错。

1 个答案:

答案 0 :(得分:11)

HTTP是无状态的;无论使用何种服务器,框架或语言,HTTP客户端都没有内在的方式来说“此请求是该会话的一部分”。这是HTTP设计的一部分。

因此,会话始终是Web应用程序的一项功能;要么是由Web应用程序框架支持,要么是在应用程序本身中实现。从无状态协议创建有状态会话的最常用方法是使用cookie;客户端将根据服务器的请求存储cookie,并在将来的请求中将这些cookie返回给该服务器。

会话数据可以序列化并存储在cookie本身中,但这样既不安全(秘密信息可能被伪造或被窃听),而且效率低(即使单个字节对客户端没用,也需要带宽),所以首选的解决方案是使用不透明(甚至更好,一次性使用)会话密钥存储在cookie中,Web应用程序将存储带外会话数据;在内存,文件系统或数据库后端,或其他一些选项。

django在“中间件”,即修改传入请求和传出响应的模块中透明地处理大部分内容。 auth中间件将读取cookie并检查是否代表登录用户,如果是,则向请求添加用户对象;当用户登录时,它还会将cookie附加到响应中。会话middlware以类似的方式工作,检查cookie,从请求之间存储的任何地方读取会话数据,还从响应中获取会话数据并存储它们,同时设置一个cookie,将客户端的会话与刚刚存储的会话数据相关联。

由于这两个功能都很有用,彼此独立(我倾向于避免会话,但通常使用某种身份验证),因此它们并不相互依赖。类似会话的身份验证以与会话类似的方式实现,但经过身份验证的用户不会存储在“会话”中,也不会将会话附加到“经过身份验证的用户”。

你可能不这么认为,但是django的身份验证系统是designed to be extended;如果您已经拥有了一个您想要进行身份验证的有效用户数据库,那么添加一个与标准django auth应用程序完全吻合的新auth后端非常简单(这意味着您还可以依次使用依赖于它的其他应用程序) )。