一(yī)圖搞懂掃碼登錄的技術原理
現在掃碼登錄是一(yī)種很常見的登錄方式。當用戶需要登錄某個網站時,網站會提供一(yī)種掃碼登錄的方式,用戶打開(kāi)相應的手機App,掃描網站上顯示的二維碼,然後在App中(zhōng)确認登錄,網站監測到用戶确認登錄後,跳轉到登錄成功頁面。從這個形式上看,掃碼登錄就是将用戶在手機App中(zhōng)的登錄狀态同步到網站中(zhōng),這篇文章就來一(yī)窺這個同步是如何發生(shēng)的。
同一(yī)産品中(zhōng)的掃碼登錄
假設有一(yī)款産品,這個産品通過手機端App和PC端應用爲用戶提供服務,爲了方便用戶在PC端上登錄,産品提供了一(yī)個掃碼登錄的功能,即PC端應用上展示一(yī)個登錄二維碼,用戶使用手機端App掃碼并确認登錄,然後用戶就可以在PC端上登錄成功。在這個例子中(zhōng),手機端App和PC端應用同屬于一(yī)個産品,這是一(yī)種常見的産品形态,微信、微博、知(zhī)乎等等都是這種産品形态的代表。
爲了方便介紹,這裏再假設PC端應用是一(yī)個Web站點,下(xià)面就來看一(yī)下(xià)這種登錄方式的運作原理:
如上圖所示,整個過程比較簡單,這裏大(dà)概分(fēn)爲如下(xià)幾個步驟:
1、用戶發起二維碼登錄:此時網站會先生(shēng)成一(yī)個二維碼,同時把這個二維碼對應的标識保存起來,以便跟蹤二維碼的掃碼狀态,然後将二維碼頁面返回到浏覽器中(zhōng);浏覽器先展示這個二維碼,再按照Javascript腳本的指示發起掃碼狀态的輪詢。所謂輪詢就是浏覽器每隔幾秒調用網站的API查詢二維碼的掃碼登錄結果,查詢時攜帶二維碼的标識。有的文章說這裏可以使用WebSocket,雖然WebSocket響應比較及時,但是從兼容性和複雜(zá)度考慮,大(dà)部分(fēn)方案還是會選擇輪詢或者長輪詢,畢竟此時通信稍微延遲下(xià)也沒多大(dà)關系。
2、用戶掃碼确認登錄:用戶打開(kāi)手機App,使用App自帶的掃碼功能,掃描浏覽器中(zhōng)展現的二維碼,然後App提取出二維碼中(zhōng)的登錄信息,顯示登錄确認的頁面,這個頁面可以是App的Native頁面,也可以是遠程H5頁面,這裏采用Native頁面,用戶點擊确認或者同意按鈕後,App将二維碼信息和當前用戶的Token一(yī)起提交到網站API,網站API确認用戶Token有效後,更新在步驟1中(zhōng)創建的二維碼标識的狀态爲“确認登錄”,同時綁定當前用戶。
3、網站驗證登錄成功:在步驟1中(zhōng),二維碼登錄頁面啓動了一(yī)個掃碼狀态的輪詢,如果用戶已經“确認登錄”,則輪詢訪問網站API時,網站會生(shēng)成二維碼綁定用戶的登錄Session,然後向前端返回登錄成功消息。這裏登錄狀态維護是采用的Session機制,也可以換成其它的機制,比如JWT。
爲了保證登錄的安全,有必要采取一(yī)些安全措施,可能包括以下(xià)若幹方法:
對二維碼承載的信息按照某種規則進行處理,App可以在掃碼時進行驗證,避免任 何掃碼都去(qù)請求登錄;
對二維碼設置一(yī)個過期時間,過期就自動删除,這樣使其占用的資(zī)源保持在合理範 圍之内;
限制二維碼隻能使用一(yī)次,防止重放(fàng)攻擊;
二維碼使用足夠長的随機性字符串,防止被惡意窮舉占用;
用HTTPS傳輸,保護登錄數據不被竊聽(tīng)和篡改。
第三方應用的掃碼登錄
現在很多網站除了提供自身賬号的登錄方式以外(wài),還提供了微信掃碼登錄、微博掃碼登錄等方式,本來這對用戶來說是十分(fēn)方便的,不過很多站點爲了獲取用戶手機号,首次登錄時還需要用手機驗證碼再登錄一(yī)次,用戶會有點被欺騙的感覺,不過這個問題不是本文要探讨的。
這裏以微信掃碼登錄某網站爲例,某網站就是第三方應用,所謂第三方是相對微信自身來說的。相比同一(yī)産品中(zhōng)的掃碼登錄,網站使用微信掃碼登錄會更複雜(zá)一(yī)些,因爲這涉及到不同應用之間的登錄安全。下(xià)面就給出這一(yī)登錄方式的詳細運作原理,時序圖比較長,不過隻要耐心點就能完全搞清楚,甚至自己實現一(yī)個類似的第三方掃碼登錄方案。
這裏對一(yī)些關鍵點特别說明下(xià):
1、步驟3 生(shēng)成微信登錄請求記錄:當用戶掃碼并同意登錄之後,步驟25中(zhōng)浏覽器會重定向到第三方應用,如果之前沒有創建一(yī)條登錄請求記錄,網站并不能确定這次登錄就是自己發起的,這可能導緻跨站請求僞造攻擊。比如使用某個應用的微信登錄二維碼,騙取用戶的授權,然後最終回調跳轉到其它站點,被回調站點隻能被動接受,雖然下(xià)一(yī)步驗證授權Code通不過,微信也可能會認爲第三方應用出了某種問題,搞不好被封掉。因此第三方應用創建一(yī)條登錄請求記錄之後,還要把記錄的标識拼接到訪問微信登錄二維碼的url中(zhōng),微信會在用戶同意登錄後原樣返回這個标識,步驟26中(zhōng)第三方應用可以驗證這個标識是不是有效的。
2、步驟17 顯示應用名稱和請求授權信息:因爲微信支持很多的第三方應用,需要明确告知(zhī)用戶正在登錄哪個應用,應用可以訪問自己的什麽信息,這都是用戶做出登錄決定的必要信息。因此掃碼之後,微信手機端就需要去(qù)微信開(kāi)放(fàng)平台查詢下(xià)二維碼對應的第三方應用信息。
3、步驟24 登錄臨時授權Code:微信開(kāi)放(fàng)平台沒有直接向浏覽器返回登錄用戶的信息,這是因爲第三方應用還需要對用戶進行授權并保持會話(huà)的狀态,這适合在應用的服務端來處理;而且直接返回用戶信息到浏覽器也是不安全的,并不能保證二維碼登錄請求就是通過指定的第三方應用發起的。第三方應用會在步驟27中(zhōng)攜帶這個授權Code,加上應用的AppId和AppSecret,再去(qù)向微信開(kāi)放(fàng)平台發起登錄請求,臨時授權Code隻能使用1次,存下(xià)來也不能再用,且隻能用在指定的應用(即綁定了AppId),AppSecret是應用從服務端提取的,用來驗證應用的身份,這些措施保證了微信授權登錄的安全性。不過驗證通過後還是沒有直接返回用戶信息,而是返回了一(yī)個access token,應用可以使用這個token再去(qù)請求獲取用戶信息的接口,這是因爲開(kāi)放(fàng)平台提供了很多接口,訪問這些接口都需要有授權才行,所以發放(fàng)了一(yī)個access token給第三方應用,這種授權登錄方式叫做OAuth 2.0。基于安全方面的考慮,access token的有效期比較短,開(kāi)放(fàng)平台一(yī)般還會發放(fàng)一(yī)個refresh token,access token過期之後,第三方應用可以拿着這個refresh token再去(qù)換一(yī)個新的access token,如果refresh token也過期了或者用戶取消了授權,則不能獲取到新的access token,第三方應用此時應該注銷用戶的登錄。這些token都不能洩漏,所以需要保存在第三方應用的服務端。
微信二維碼登錄的變種
微信除了跳轉到二維碼登錄頁面的方式,還提供了第三方網站中(zhōng)内嵌二維碼的方式。通過微信JS SDK生(shēng)成二維碼并在網頁的指定區域展現,用戶掃碼同意登錄後,微信JS SDK發起重定向或者在iframe中(zhōng)打開(kāi)應用回調頁面,傳遞臨時授權Code和應用State,後續的流程就都一(yī)樣了。
另外(wài)這裏的第三方應用如果是移動端App,微信開(kāi)放(fàng)平台也支持掃碼登錄的方式,區别在于需要集成微信SDK,獲取二維碼和接收用戶授權Code都是通過SDK回調的方式,後續的流程也都一(yī)樣。
作者:螢火(huǒ)架構
鏈接:https://juejin.cn/post/7056544865647067172
來源:稀土掘金
掃二維碼與項目經理溝通
我(wǒ)們在微信上24小(xiǎo)時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯網交流