?? 背景
關(guān)于我昨天突然接到神秘“面試”:微信掃碼授權(quán)登錄的實(shí)現(xiàn)邏輯是神魔?在這個(gè)掃碼授權(quán)的過(guò)程中客戶端、服務(wù)端、微信平臺(tái)都做了些神魔?二維碼里面又有哪些信息?
從手機(jī)微信掃一掃二維碼到登錄個(gè)人的知乎賬戶,中間究竟發(fā)生了什么,是怎么做到的呢?

在了解它底層具體怎么實(shí)現(xiàn)之前,我們可以先去了解怎么去實(shí)現(xiàn)這個(gè)微信授權(quán)登錄,如何給自己的網(wǎng)站加上微信授權(quán)登錄?
?? 微信開(kāi)放平臺(tái)申請(qǐng)
登錄微信開(kāi)放平臺(tái),申請(qǐng)開(kāi)發(fā)的賬號(hào)
來(lái)到網(wǎng)站應(yīng)用頁(yè)面創(chuàng)建網(wǎng)站應(yīng)用:

在此處填好信息以及回調(diào)的域名,具體回調(diào)域名要寫什么在后面會(huì)有講解,在通過(guò)申請(qǐng)后可以拿到APPID
和APPSECRET
進(jìn)行開(kāi)發(fā)者的資質(zhì)認(rèn)證,需要繳納300元:

?? 獲取網(wǎng)頁(yè)的二維碼
做完上面的事情之后,我們就拿到了三個(gè)屬性:APPID、APPSECRET、回調(diào)域名
,接下來(lái)我們就可以獲取網(wǎng)頁(yè)的二維碼了
這個(gè)二維碼是微信生成的,我們只需要按下面的格式鍵入正確的地址和參數(shù)就可以獲取:
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
該請(qǐng)求所需要配置的參數(shù)列表為:
參數(shù) | 是否必須 | 說(shuō)明 |
---|
appid | 是 | 應(yīng)用的唯一表示,在上面的申請(qǐng)中拿到了 |
redirect_uri | 是 | 回調(diào)的域名,也就是上面填的哪個(gè)域名 |
response_type | 是 | code ,此處就是一個(gè)占位符,后續(xù)會(huì)使用它進(jìn)行授權(quán)獲取access_token 和openId |
scope | 是 | 網(wǎng)頁(yè)授權(quán)填寫:snsapi_login ,表示應(yīng)用授權(quán)的作用域 |
state | 否 | 用于防止CSRF攻擊(跨站請(qǐng)求偽造攻擊) |
我們以知乎的舉例,可以拿到知乎的登陸的二維碼的URL為:
https://open.weixin.qq.com/connect/qrconnect?appid=wx268fcfe924dcb171&redirect_uri=https://www.zhihu.com/oauth/callback/wechat?action=login&from=&&response_type=code&scope=snsapi_login#wechat
看上面的URL我們可以得出它的參數(shù)列表為:
?? 輪詢請(qǐng)求檢查狀態(tài)
通過(guò)上面那個(gè)地址我們可以來(lái)到知乎的微信二維碼授權(quán)登錄頁(yè)面,打開(kāi)控制臺(tái),我們就可以發(fā)現(xiàn)有一個(gè)請(qǐng)求一直在進(jìn)行輪詢,每15s進(jìn)行一次輪詢:

我們具體來(lái)分析一下這個(gè)輪詢的方法,可以看到這個(gè)輪詢的方法里面有兩個(gè)參數(shù):
uuid
:我認(rèn)為是進(jìn)行標(biāo)識(shí)機(jī)器的一個(gè)ID,每一個(gè)二維碼都對(duì)應(yīng)一個(gè)唯一的UUID,因?yàn)槊恳淮蔚亩S碼都是不一樣的,這樣我們就可以在微信掃描之后,知道微信與哪一臺(tái)機(jī)器進(jìn)行綁定,進(jìn)而在授權(quán)之后進(jìn)行一個(gè)重定向
-
:計(jì)數(shù)器,上述的十來(lái)個(gè)請(qǐng)求,它的計(jì)數(shù)器會(huì)依次加一

如果我們長(zhǎng)期不掃碼,它就會(huì)一直輪詢請(qǐng)求,在過(guò)去一定時(shí)間后會(huì)刷新二維碼,如果不掃碼,它返回的結(jié)果就一直為:window.wx_errcode = 408;window.wx_code = ''

?? 微信掃一掃
?? 1.掃碼成功
在我們進(jìn)行掃碼之后,頁(yè)面會(huì)變?yōu)椋?/p>

此時(shí)進(jìn)行輪詢的接口的查看響應(yīng),可以發(fā)現(xiàn)是window.ex_errcode = 404; window.wx_code = ''
,也就是說(shuō)由最開(kāi)始的狀態(tài)碼408
轉(zhuǎn)為404

? 2.授權(quán)失敗
手機(jī)上的頁(yè)面為,在掃碼成功后,就會(huì)調(diào)起微信OAuth2.0
,請(qǐng)求微信授權(quán)登錄

如果拒絕授權(quán),返回的狀態(tài)碼就為:window.ex_errcode = 403; window.wx_code = ''
,頁(yè)面跳轉(zhuǎn)到
?
? 3.授權(quán)成功
而我們?nèi)绻跈?quán),此時(shí)返回回來(lái)的數(shù)據(jù)就是:window.wx_errcode=405;window.wx_code='061xgj000c2DHP1dpk400y062z2xgj00';
此時(shí)微信SDK判斷到返回的code
為405
,并且code
不為空
就會(huì)拿到code然后重定向我們之前配置的回調(diào)的域名
重定向的好處就是,請(qǐng)求是瀏覽器發(fā)出的,而不是遠(yuǎn)程調(diào)用的,這樣我們就知道這個(gè)code是對(duì)應(yīng)的哪一個(gè)瀏覽器,也就是有了微信授權(quán)信息和瀏覽器的對(duì)應(yīng),如果要進(jìn)行cookie
的設(shè)置也可以:

帶上我們的code,此時(shí)就可以在后臺(tái)的程序中通過(guò)代碼,完成以下步驟:
3.1 Gitee實(shí)現(xiàn)方案
這里我看Gitee的方案是,在請(qǐng)求到這個(gè)接口后,在cookie中存入個(gè)人信息,并重定向回網(wǎng)頁(yè)(后臺(tái)進(jìn)行重定向):

重定向回了https://gitee.com/dashboard
,因?yàn)閏ookie中有了個(gè)人信息了,所以就能登錄成功
3.2 知乎實(shí)現(xiàn)方案
而知乎的做法是返回一段前端代碼,然后調(diào)用了一個(gè)登錄的接口,進(jìn)而重定向到主頁(yè):


?? 總結(jié)
至此,從微信掃碼授權(quán)登錄到網(wǎng)頁(yè)獲得授權(quán)信息成功登陸的具體流程就講完了,大概的過(guò)程就是:
在微信開(kāi)放平臺(tái)進(jìn)行配置和申請(qǐng),獲得APPID APPSECRET
,配置好自己的回調(diào)URI
根據(jù)拿到的數(shù)據(jù),配上指定的參數(shù)得到二維碼的URL
微信SDK在二維碼頁(yè)面進(jìn)行15s一次輪詢檢測(cè),對(duì)于不同的狀態(tài)有不同的狀態(tài)碼:
如果沒(méi)有掃碼:狀態(tài)碼為408,且code為空
如果掃碼既不接受也不拒絕授權(quán):狀態(tài)碼為404,且code為空
如果掃碼但是拒絕授權(quán):狀態(tài)碼為403,且code為空
如果掃碼并且同意授權(quán):狀態(tài)碼為405,返回一個(gè)code
微信SDK檢測(cè)到狀態(tài)碼和code后,進(jìn)行對(duì)之前配置的回調(diào)URI
的重定向,帶上code
這個(gè)時(shí)候就來(lái)到了服務(wù)端,也就是后臺(tái),后臺(tái)根據(jù)code
依次獲取access_token openid
和個(gè)人信息
如果參照Gitee的做法,就可以直接把身份信息存入Cookie,然后重定向到主頁(yè),至此,登錄結(jié)束
??友鏈