Session
session 的数据存在数据库中,它在客户端是用 cookie 来识别的,作为一个票据。这个 cookie 的名称,默认就叫 "sessionid",但是可以通过 settings.SESSION_COOKIE_NAME 来修改。
sessionid 这个 cookie 的值,在服务器端就是 session 的 session_key 属性,同时数据库的 django_session 表中用它作为主键。
session 的实现涉及下列几个主要的类:
1. Session 和 SessionManager.
这两个是 session 的 Model 及其相应的 Manager. 它们负责:
(1) session 和数据库之间的持久化操作
(2) session_key 的生成机制
(3) session 内容(是一个字典)的序列化/反序列化工作。
实际应用中,我们不会直接用到这两个类。
2. SessionWrapper
实现了 session 类似字典的一些功能,如设值、取值等。这个类是 request.session 对象的实际类型。
3. SessionMiddleware
属于 django 自带的中间件之一,作用是在 request 中附加 session 属性,并可以在 response 的时候,适当的情况下保存 session 并发出相应的 cookie 到客户端。
session 的几个可配置的参数:
settings.SESSION_SAVE_EVERY_REQUEST
settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
settings.SESSION_COOKIE_AGE
settings.SESSION_COOKIE_SECURE
settings.SESSION_COOKIE_DOMAIN
settings.SESSION_COOKIE_NAME
User
request.user 中保存的 user 对象,是 lazy-load 的,有缓存。
用户的身份验证过程:
1. 首先通过 authenticate() 方法对传入的用户名、密码等信息进行验证,如果符合,则返回相应的 user 对象,同时,该方法会对 user 对象加以标注,通过附加 user.backend 属性来记录验证是被哪个配置的 backend 通过的。默认只有一个 backend,是 django.contrib.auth.backends.ModelBackend.
2. login 方法调用
如果上一步身份验证通过,则此方法中对 request.session 中简单的添加两个键值:
(1) "_auth_user_id" 这个是 user.id
(2) "_auth_user_backend" 这个是 user.backend
而实现 request.user 属性同样是通过 Middleware 来完成的,其中调用到一个 get_user 方法,该方法尝试读取上面在 session 中记录的 user.id 和 user.backend, 然后命令 backend 去查找相关 id 的 user 对象。如果没有找到,则返回一个 AnonymousUser. 而 AnonymousUser 是一个空实现,不具备 user 的任何功能。
可以通过 is_anonymous() 或 is_authenticated() 来判别是否为匿名用户。
小结
django 中 user 和 session 关系不大,仅仅是在其实现中利用 session 保存了 user.id 和 user.backend 两个值。