1、背景php
最近在作一個面向三端【H五、IOS、安卓】的短信驗證碼登陸接口。發送短信驗證碼時,服務端經過 session 保存驗證碼的值。登陸時,從 session 獲取驗證碼和用戶輸入的驗證碼java
相比較。在這過程當中,H5 端 session 的設置、讀取都沒有問題。可是 IOS 、安卓端能夠正常設置 session 值,可是在登陸時,讀取的 session 值爲空,致使業務邏輯異常中斷。數據庫
2、緣由編程
一、PC 端多個請求,會使用同一個 PHPSESSID ;數組
二、移動端【IOS 安卓】多個請求,會使用不一樣的PHPSESSID。好比發送驗證碼時的 PHPSESSID = t5arr13hh352gaekn255jvrk36,登陸時的 PHPSESSID = 44jh1hgcc07v0bi07i652vbnv1;瀏覽器
由於 PHPSESSID 的不一致,致使了移動端【IOS 安卓】不能正常讀取 session 值。服務器
3、參考解決方案cookie
移動端人爲設置 PHPSESSID ,並保持有業務管理的接口中的 PHPSESSID 一致便可。session
4、Session 原理
數據結構
提到session,你們確定會聯想到登陸,登陸成功後記錄登陸狀態,同時標記當前登陸用戶是誰。功能大致上就是這個樣子,可是今天要講的不是功能,而是實現。經過探討session的實現方式來發掘一些可能你以前不知道的有趣的事情。
爲了記錄session,在客戶端和服務器端都要保存數據,客戶端記錄一個標記,服務器端不但存儲了這個標記同時還存儲了這個標記映射的數據。好吧,仍是說點白話吧,在客戶端記錄的實際上是一個sessionid,在服務器端記錄的是一個key-value形式的數據結構,這裏的key確定是指sessionid了,value就表明session的詳細內容。用戶在作http請求的時候,老是會把sessionid傳遞給服務器,而後服務器根據這個sessionid來查詢session的內容(也就是上面說到的value)。
如今咱們重點關注一下sessionid,他是今天問題的關鍵所在。sessionid在客戶端(http的客戶端通常就是指瀏覽器了)是存儲在cookie中,固然也有例外(書本上確定會提到也有保存在url中的)。
咱們經過一個例子來闡述一下這個sessionid在session處理時的做用。首先假定這麼一個場景,咱們有一個cms(content management system,內容管理系統),這個應用有一個後臺,用戶必須登陸才能進入後臺進行文章發表等操做。首先是登陸流程,用戶在瀏覽器輸入用戶名、密碼,點擊登陸,瀏覽器會將用戶名密碼提交到服務器程序進行處理;服務器驗證用戶名、密碼正確後,會返回登陸成功信息,而且會修改服務器端的session內容,好比咱們將用戶ID寫入session中,爲了方便存儲這些session的內容會被序列化成字符串或者二進制保存在文件或者數據庫中,這時候大多數狀況下服務器在對當前的http請求進行響應時,會返回一個新的sessionid要求瀏覽器寫入本地cookie中,對應的返回的http響應頭部信息應該會是是這個樣子的:set-cookie:PHPSESSID=xxxxxxx,瀏覽器解析到這個頭以後就會在當前生成一個cookie關聯當前的域名。
接着用戶登陸後臺進行發表文章操做,登陸用戶填寫文章的標題、內容,而後點擊發送。這時候瀏覽器會生成一條到服務器的http請求,注意這個請求的頭部會將存儲sessionid的cookie內容發送過去,也就是說請求的http頭部信息中應該會有這麼一段數據:cookie:PHPSESSID=xxxxxxx;other_cookie_name=yyyyyy;服務器接收到這個http請求以後,解析到cookie存在,且cookie中存在PHPSESSID這個cookie名字,而後就將PHPSESSID的值(也就是sessionid的值)取出來,根據這個PHPSESSID查詢服務器上有沒有對應的session內容,若是有則將其對應的值取出來進行反序列序列化(也就是將其轉成編程語言中的一個數據結果,好比在php中會獲得一個$_SESSION數組,在j2ee中會獲得類型爲javax.servlet.http.HttpSession),方便在程序中進行讀取,最終服務器認定session中儲存的值存在,而且從反序列化獲得的對象中讀取到了用戶ID屬性,而後就往cms數據庫的文章表中插入了一條數據,最終返回http響應,告訴瀏覽器操做成功了。