Odoo 使用 cookie 来携带 session_id, session id 是一个哈希值,在 odoo/http.py setup session 之中可以看到,除了通过 cookie 携带,还可以通过请求的参数携带,或者 http header 中携带 session id。这里只讨论使用 cookie 携带 session id 的情形。
def setup_session(self, httprequest): # recover or create session session_gc(self.session_store) sid = httprequest.args.get('session_id') explicit_session = True if not sid: sid = httprequest.headers.get("X-Openerp-Session-Id") if not sid: sid = httprequest.cookies.get('session_id') explicit_session = False if sid is None: httprequest.session = self.session_store.new() else: httprequest.session = self.session_store.get(sid) return explicit_session
session id 会对应一个文件存在于 Odoo 配置的 data dir目录下。
session id 对应的文件里面包含着真正的 session 信息,主要是用户 id,数据库,用户语言等上下文信息。如果系统有这个上下文信息说明用户正在和系统对话,并且已经获得了系统的认证,不需要用户每次执行操作都提供用户名和密码重新获得授权。
session 的建立过程就是用户登录过程,用户登录成功即获得了一个有效的 session 存于 Odoo 的后台系统
Odoo 用户在登录系统的时候会要求数据用户名和密码,有的还要求提供数据库名称。用户名密码通过表单 POST 到 web/login,web/login 同时支持 GET 和 POST,GET 就是返回 HTML 页面,POST 就是提交用户名密码验证用户。
POST 登录表单的时候必须要提供一个 csrf token,这个是 Odoo 的一个增强的安全机制。csrf token 是通过 GET web/login 这个页面的时候,Odoo 后台生成写到网页表单的隐藏 input 里面。这样当用户 POST 表单的时候会把csrf token携带过来。
csrf token 有两种,一种是包含最大时间戳的,就是说这个 token 会过期,登录的时候使用的 csrf token 就是有时间戳要求的。而其他 Odoo http 请求都是不用携带时间戳的 csrf token。携带时间戳的 csrf token 一般通过后台生成 html 的时候写成隐藏 input 元素放在表单里面;不带时间戳的 token 会通过 odoo 这个全局的 js 对象获取(后台生成 js 代码)。比如下载一个系统的图片或者附件都是需要这个csrf token 的这个token 就不需要 max ts (时间戳)。
如果 POST web/login 成功,Odoo 会发送一个重定位请求,让前端浏览器访问 web/,这时候同时 set 了 cookie 其中就包含了授权的 session id,这样再请求 web,Odoo 后台就给前端设置好一个 odoo js 对象并且包含了 session 信息,即前端的 js 可以直接通过 odoo js 对象访问到 session 对象。
重定向成功后,就可以进行授权操作了,所有的 Odoo Jsonrpc ,都能正常执行了。当然每次请求要带上 设置了 session id 的 Cookie;要求提供 csrf token 的api 还要提供csrf token,很多 api 不要求 csrf token,是否要求看看 controller 中的接口装饰,默认是要求提供。