Odoo 使用 cookie 來攜帶 session_id, session id 是一個哈希值,在 odoo/http.py setup session 之中可以看到,除了通過 cookie 攜帶,還可以通過請求的參數(shù)攜帶,或者 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 會對應一個文件存在于文件系統(tǒng)之中,如果在 Linux 中,并且沒有特意配置過,在 ~/.local/share/Odoo Product Name/下面,Odoo Product Name 是產品名稱是可以配置的,這個目錄實際上是 Odoo 默認的 data dir。如果啟動的時候指定 data dir,session 存儲的位置也會改變。data dir 下面 filestore 目錄,存儲 Odoo 文件(按照數(shù)據(jù)庫名稱不同再分一層目錄),曾經有朋友問過,Odoo 的文件存數(shù)據(jù)庫嗎,大概率不是的,文件一般存在這里。
session id 對應的文件里面存儲真正的 session 信息,主要是用戶 id,數(shù)據(jù)庫,用戶語言等等一些用戶的上下文信息。如果系統(tǒng)有這個上下文信息說明用戶正在和系統(tǒng)對話,并且已經獲得了系統(tǒng)的認證,不需要用戶每次執(zhí)行操作都提供用戶名和密碼重新獲得授權。
session 的建立過程就是用戶登錄過程,用戶登錄成功即獲得了一個有效的 session 存于 Odoo 的后臺系統(tǒng);當然任何非法的訪問,肯定是無法取得一個 session 的,如果能取得 session 就是合法訪問。
Odoo 用戶在登錄系統(tǒng)的時候會要求數(shù)據(jù)用戶名和密碼,有的還要求提供數(shù)據(jù)庫名稱。用戶名密碼通過表單 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 代碼)。比如下載一個系統(tǒng)的圖片或者附件都是需要這個csrf token 的這個token 就不需要 max ts (時間戳)。
如果 POST web/login 成功,Odoo 會發(fā)送一個重定位請求,讓前端瀏覽器訪問 web/,這時候同時 set 了 cookie 其中就包含了授權的 session id,這樣再請求 web,Odoo 后臺就給前端設置好一個 odoo js 對象并且包含了 session 信息,即前端的 js 可以直接通過 odoo js 對象訪問到 session 對象。
重定向成功后,就可以進行授權操作了,所有的 Odoo Jsonrpc ,都能正常執(zhí)行了。當然每次請求要帶上 設置了 session id 的 Cookie;要求提供 csrf token 的api 還要提供csrf token,很多 api 不要求 csrf token,是否要求看看 controller 中的接口裝飾,默認是要求提供。
@http.route('/web/database/create', type='http', auth="none", methods=['POST'], csrf=False)
def create(self, master_pwd, name, lang, password, **post):
try: ....
指定了 False 就是不要求。上邊的創(chuàng)建數(shù)據(jù)庫操作就是不要求提供 csrf token。
@http.route('/web/binary/upload_attachment', type='http', auth="user")
@serialize_exception
def upload_attachment(self, callback, model, id, ufile):
files = request.httprequest.files.getlist('ufile')
Model = request.env['ir.attachment']
out = """<script language="javascript" type="text/javascript">
var win = window.top.window;
win.jQuery(win).trigger(%s, %s);
</script>"""
args = []
而這個上傳 attachment 的操作就必須要提供 csrf token,注意的是 csrf token 必須要通過表單參數(shù)提交。JSONRPC 沒有 csrf token 的需要。
退出系統(tǒng)應該不用介紹了吧。自己找找看吧 ??!