Wednesday, October 21, 2009

django的auth与session

一直对网站的认证感兴趣. 看了一把django在这方面的实现方式:
认证有两部分, 一是session, 二是用户的信息(密码等).

django的contrib.auth是基于contrib.session的
django是怎么生成request.session和request.user的呢?

因为request.session和user都是在view被调用之前生成的. 所以使用到了中间件:
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
)

django.contrib.sessions.middleware.SessionMiddleware的内容:
class SessionMiddleware(object):                                                                                  
    def process_request(self, request):                 
        engine = import_module(settings.SESSION_ENGINE)
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
        request.session = engine.SessionStore(session_key)    
django在默认情况下使用数据库存放session, 它还实现了方式存放session的方法. 可以通过SESSION_ENGINE来配置
初始化SessionStore时需要一个参数, 如果没有显式给出就是None, 代码:
class SessionBase(object):
    """
    Base class for all Session classes.
    """
    TEST_COOKIE_NAME = 'testcookie'
    TEST_COOKIE_VALUE = 'worked'

    def __init__(self, session_key=None):
        self._session_key = session_key
        self.accessed = False
        self.modified = False
SessionStore可以使用的方法在SessionStore和SessionBase两个类中可以找到

对于request.user的情况:
django.contrib.auth.middleware.AuthenticationMiddleware的内容
class LazyUser(object):
    def __get__(self, request, obj_type=None):
        if not hasattr(request, '_cached_user'):
            from django.contrib.auth import get_user
            request._cached_user = get_user(request)
        return request._cached_user

class AuthenticationMiddleware(object):
    def process_request(self, request):
        assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
        request.__class__.user = LazyUser()
        return None

很短,就一个构造函数! 但是python的__get__有意思! AuthenticationMiddleware中只是实现了request.user的引用. 平时django应用使用request.user的方式:
1. request.user.name
2. request.user.is_authenticated()
上面的request.usr不只是一个LazyUser的实例吗? 怎么与django.contrib.auth.models.User关联在一起?

重点在于LazyUser的__get__方法. 关于这种用法, 下次认真做记录

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.