註冊、登陸是服務端常作的功能,主要涉及用戶信息表單提交、會員信息保存、登陸狀態維護,前端除了表單提交外也沒有什麼可參與的,能發揮的做用不多。javascript
若是經過nodejs介入開發,則可參與更多,這也是爲何建議你們學習下nodejs,經過服務端語言來加強本身的技術棧,技術研發是一個綜合類的能力,相比較Java,單純依靠前端是難以支撐技術的體量,這也是前端人員發展後期所面臨的尷尬,若之前端爲主體,知曉服務端、數據庫、運維、測試等技術棧,則能支撐更寬更深的技術體量。html
前段時間爲公司項目提供了sso解決方案,這裏分享下。前端
登陸重點在於會員狀態的維護、保持,初級者有兩個誤區java
使用數據庫保持登陸狀態node
即收到用戶登陸信息後,將狀態維護在數據庫,這樣是可行的,但效率是很是低,由於後續每次涉及到用戶權限的頁面、數據獲取都須要先驗證狀態,經過數據庫操做耗時redis
單純使用session數據庫
這算不上一個誤區,也是教程經常使用的方式,不過session一般是保存在當前服務的緩存裏的,單臺服務可行,但多臺服務器集羣時,session沒法共享json
基於上面兩種狀況,咱們須要一個可被多臺服務器快速訪問的獨立服務 -- redis。memcache也可達到,不過相比之下,redis功能、穩定性都更好。後端
先後端分離時我採用了下圖的架構,可參考 全棧技術棧api
分離架構中流程以下
用戶在client輸入username + password,提交到Node服務,Node對數據作規則有效性驗證,錯誤則返回,經過則發給java到DB作信息驗證,會員信息有效,由java端生成sessionId,經過http-header-cookie,由nodejs保存到客戶端的cookie裏,同時由java將sessionId保存到獨立的緩存服務器redis裏,以sessionId爲key,能夠多保存一些不適合保存在客戶端的信息,如權限。
當客戶端請求用戶數據時,http會自動帶上cookie,nodejs檢查是否有sessionId,如無,或在redis裏不存在,則返回錯誤或redirect到login.html,如有,則繼續請求java,一般任何一個涉及到用戶信息的請求,不管是renderView,仍是fetchData,都須要驗證,因此須要頻繁的獲取驗證,此時redis的緩存讀取效率更高。
用戶退出時,由nodejs清空cookie,及redis裏的sessionId,便可。
瀏覽器出於安全考慮,實現了同源策略,對於跨站請求可使用jsonp或設置http的Access-Control-Allow-Origin實現跨域。
同源策略對cookie的訪問限制,形成不一樣域沒法相互訪問(二級域名能夠訪問主域)。因此若A/B兩個不一樣域名的站點,使用同一套會員體系,也沒法同時登陸(如baidu.com / hao123.com),而實際項目中咱們須要處理這樣的問題,即會員A站登陸後,打開B站也要保持該會員的登陸狀態,個人實現見下圖
A/B兩站,分別有客戶端和服務端,單站登陸的客戶端與服務端的通訊見前圖,此處不在描述,涉及跨站的流程大體以下
會員在A站登陸,A站服務端生成sessionId外,再額外生成一個ticket,設置3s時效,以請求返回值的形式返回給客戶端,以下,同時,將ticket以{ticket: sid}形式保存在redis裏
#返回值 { code: 0, message: 'signin success', data: {ticket:'ffqwoij1230340lklfdf123fklk' }
A站客戶端收到返回後,請求B站的連接,如
B.com/api/auth.gif?ticket=ffqwoij1230340lklfdf123fklk
B站服務端收到該請求後,獲取該ticket,到redis內驗證該ticket存在,且取到sessionid,再將sessionid,經過http-header-cookie輸出到B站客戶端的cookie裏,即爲B添加的會員狀態的標識。同時刪除redis裏的ticket。
A/B站都使用了同一個sid,且保存在同一個redis裏,因此任何一方因退出而清空redis.sessionid的操做,都會引發其它站點的退出。
注意如下幾點:
A站收到ticket後,立刻發出B站的請求作登陸驗證,間隔時間很短,3S一般是夠了,設置時效性,也更安全
ticket的生成須要加入請求的客戶端信息,以便數據被攔截後在其它環境非法登陸,如IP等信息
發向B站的請求,一般有圖片、iframe兩種形式,後者太重,圖片形式較輕。
思考該方案時參考了百度的實現,也只是參考了其發圖片請求這一點,其內部的機制並不瞭解,加上本身的思考實現這一套方案,且用於公司的項目上。
若須要兩個以上的域名登陸,處理相同。
參見百度的實現,能夠看到其發出了多個crossdomain請求,每一個都是向不一樣的域發出的請求,如hao123.com、anquanbao.com等