寫在前面
時間:2017-05-29 7:30
距離上篇文章釋出已經一個多月了,本來自己的計劃是一週一記,怎麼就變成月記了呢?最近工作的事情忙的焦頭爛額,當然也不能排除我懶的要死的因素,有時間追擇天記怎麼就不能寫篇部落格呢?暗暗自責一分鐘…
今天是端午節小長假的第二天,第一天約好和舍友逛頤和園的計劃被帝都36度的高溫打回來了,於是乎這幫哥們又抱著手機開黑到深夜。昨天虛度了一天,今兒一早起來雄心滿滿的要繼續昨天的計劃,無奈這幾個老年人又不起床。我善心作祟,想著打擾人家美夢太不禮貌,那就,寫篇部落格吧,理一理一個多月來亂七八糟的事情,要不然,月記也得成年記了。
對了,在這之前,首先要祝大家端午節快樂!嘎嘎
正文
切入正題。回顧這一個多月亂七八糟的事情,其實就是一個傳統的PHP程式設計師,拿著一套沒有做使用者登入狀態的App介面,在考慮如何利用session建立使用者會話,在介面服務端儲存使用者資訊和登入狀態。
這裡要吐槽一下
ci
框架,奇葩的重寫session機制,搞得我在postman中就是獲取不到session的值,浪費不少時間。所以同志們,選擇框架要慎重啊!
我拿到的API介面,是沒有做任何請求驗證的,就是任何人拿到介面地址就可以直接呼叫,這是極不安全的。我在考慮要做驗證的時候,首先想到的就是傳統的cookie+session
機制。但是一般的API又會在請求引數或者請求頭中加一個token
。所以我的方案是:當使用者登入驗證通過之後,在服務端session中儲存使用者資訊和一個與之匹配的token,然後將該token返回客戶端,表示登入成功。接下來使用者的每一次請求操作,都需要將該token帶到請求頭中。
這樣做相當於加了兩層驗證。第一層就是session驗證,傳統的web後臺驗證方式。第二層是將請求頭中token與session中的token匹配,全部通過,才可以去跑介面中的邏輯。
安全性做到了,下面要接客戶端了。其實在接入之前,我就有點範嘀咕,客戶端不會拿不到session吧?果然怕什麼來什麼,安卓那邊告訴我session錯誤,取不到值。
其實這很正常,web開發中session用起來簡單快速,那是因為瀏覽器幫我們做了很多事情。比如在session建立的時候,瀏覽器返回的響應頭中會有Set-Cookie
的選項,幫我們在瀏覽器本地建立cookie
來儲存上一步session建立時所生成的sessionid
,然後下一次請求的時候又會在請求頭中帶上這個cookie,通過 cookie 中的 sessionid 找到對應的session資料。就好比 session 是一張使用者表,cookie 中的 sessionid 就是使用者表的主鍵 id,瀏覽器獲取 session 資料的過程就好比是通過主鍵 ID 查詢資料表的某條資料的過程。
但是在API中,雖然可以接收到響應頭中的 set-cookie, 卻不會在下一次的請求頭中自動新增 cookie。沒有傳送sessionid,自然找不到 session 資料。所以在API中,傳送請求頭中的cookie,需要我們手動完成。
和安卓那邊溝通,他們表示框架中可以模擬瀏覽器行為,實現 cookie 的自動傳送。但是這套介面不光給app用,pc網頁端也在用。如果要在 php curl 請求介面時手動去找 cookie 併傳送,無疑會增加介面的負重,而且麻煩的很。思慮再三,我們決定放棄這種驗證方式。
我糾結的是,如果不用session,那麼在呼叫獲取使用者資訊介面的時候,至少要將user_id作為引數傳過去,但是session模式對於這種方式是不認可的,因為使用者資訊要在登入之後從session獲取,而不是通過客戶端直接傳遞,這會有風險。同時session最關鍵的還是儲存使用者登入狀態,如果沒有session,如何知道當前使用者是誰?是否在登入狀態?是否登入過期?
轉不過彎來,於是就去查百度,逛論壇,翻來覆去,最後發現一句話很關鍵:API是無狀態的。
對,
API是無狀態的
,至少 restful 是這樣!
API無狀態,開始不理解,可是它的合理性又在慢慢得到證實。如果api無狀態,那麼狀態只能是存在app客戶端。事實上確是如此,web中使用者狀態存在伺服器,而app存在客戶端。
還有一種狀況,就是現在流行的前後端分離架構,使用者狀態又該存到哪?我記得之前看過相關的文章,解決方案是在前端與API之間加一個 node 作為中間層。我一直不知道這層 node 是用來幹嘛的,不過按照現在理解,這層 node 負責請求API,然後建立和維護 session 會話。我就是按照這種方式去做,目前看來是可行的。
所以,扯了這麼多,疑問滿滿,牢騷滿滿。如果你覺得web開發和api開發的區別就是前者渲染頁面,後者輸出資料,那麼 session 會是你繞不開的梗。session機制不是筆試題上表述session和cookie區別的答案那麼弱智,你至少需要補充 http 的知識,理解請求和響應。
回到標題,api下是否使用session?標題的結尾是個問號,所以自己考慮嘍。如果你沒有session情結,或許,jwt
是你更好的選擇。