淺析微信內(nèi)Web App自動(dòng)登錄
最初是在Tower.im的公眾號(hào)里見(jiàn)到了WebApp自動(dòng)登錄,想做一個(gè)同樣效果的。那時(shí)候?qū)娞?hào)開(kāi)發(fā)不熟悉,問(wèn)了一些人也說(shuō)的稀里糊涂的,文檔又亂,***花了好長(zhǎng)時(shí)間才實(shí)現(xiàn)。這個(gè)功能需要的接口是「網(wǎng)頁(yè)授權(quán)獲取用戶(hù)基本信息」,需要認(rèn)證企業(yè)號(hào)才能使用。如果沒(méi)有權(quán)限的話(huà)可以試一下微信之門(mén),我也只是知道這個(gè)東西,從來(lái)沒(méi)試過(guò)。
基本的思路是通過(guò)公眾號(hào)OAuth API獲取用戶(hù)微信的openid。***次使用的時(shí)候讓用戶(hù)登錄,然后在數(shù)據(jù)庫(kù)里把openid和自己應(yīng)用的userid對(duì)應(yīng)起來(lái)。以后獲得用戶(hù)的openid之后就可以自動(dòng)登錄到對(duì)應(yīng)的用戶(hù)上。
我的Web App是用AngularJS實(shí)現(xiàn)的SPA,登錄之后獲取一個(gè)token放在localStorage,給后端發(fā)請(qǐng)求的時(shí)候,把token寫(xiě)在Header的Authorization里。
這個(gè)過(guò)程中不需要使用Cookie,但是為了減少跳轉(zhuǎn)次數(shù),還是用了Cookie。我把和微信登錄相關(guān)的功能寫(xiě)在了幾個(gè)PHP單頁(yè)里,用一個(gè)redirect.php做入口,把要跳轉(zhuǎn)的頁(yè)面放在參數(shù)里,由redirect.php檢查用戶(hù)是否已經(jīng)獲得了token,在獲取到token之后跳轉(zhuǎn)到目標(biāo)頁(yè)面。
登錄流程圖如下:
其中和微信有關(guān)的操作就是第二行和第三行。
微信的OAuth認(rèn)證方式是,讓用戶(hù)在微信客戶(hù)端里打開(kāi)這樣一個(gè)地址https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect,微信認(rèn)證服務(wù)器會(huì)引導(dǎo)用戶(hù)跳轉(zhuǎn)到你指定的REDIRECT_URI,并且在該URL后面加上一個(gè)CODE參數(shù)。
例如,想在http://example.com/redirect.php?type=post頁(yè)面獲得用戶(hù)的信息,就在頁(yè)面內(nèi)使用isset($_GET['code'])判斷是否存在code參數(shù)。
如果不存在,就讓用戶(hù)訪(fǎng)問(wèn)https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=http%3a%2f%2fexample.com%2fredirect.php%3ftype%3dpost&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect。(注意把url作為參數(shù)時(shí)要經(jīng)過(guò)UrlEncode)
微信服務(wù)器會(huì)把用戶(hù)重定向到http://example.com/redirect.php?type=post&code=CODE。開(kāi)發(fā)者就可以從url參數(shù)中獲得CODE了。
然后開(kāi)發(fā)者就可以拿著這個(gè)CODE,去https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code換取用戶(hù)的openid。
拿到openid之后就可以判斷用戶(hù)是否綁定過(guò),并進(jìn)行下一步操作了。
如果需要用戶(hù)的昵稱(chēng)、頭像等更多信息,需要將***個(gè)url中的scope參數(shù)改為snsapi_userinfo,詳細(xì)信息可以看微信的開(kāi)發(fā)文檔。