簡(jiǎn)述
最近項(xiàng)目中有關(guān)于第三方登陸的需求,第三方Facebook以及Google +登錄。
正好這幾天把這個(gè)需求做得差不多了,收個(gè)尾,作為一個(gè)這方面之前基本從未涉及的小白,總結(jié)下開發(fā)流程以及過程中遇到的一些問題。希望能對(duì)大家有所幫助。
? ? ? ?基本上,目前互聯(lián)網(wǎng)上的涉及到第三方登錄采用的都為OAuth認(rèn)證方式,相關(guān)原理以及實(shí)現(xiàn)方法相關(guān)的可以網(wǎng)上搜索查看。不過涉及到Facebook以及Google +的登陸,最大的問題是這兩個(gè)網(wǎng)站在墻外,想FQ找資料比較費(fèi)勁,奈何國(guó)內(nèi)這方面的資料也不是很齊全,翻到的官方的文檔又全是英文的,閱讀無能~
第三方登陸簡(jiǎn)單可以分為以下幾個(gè)步驟,分別是:獲得第三方登陸許可認(rèn)證;根據(jù)規(guī)范添加頁面登錄樣式和js實(shí)現(xiàn),跳轉(zhuǎn)到第三方登陸頁面登陸并獲取授權(quán)后,返回原指定頁面(或請(qǐng)求);后臺(tái)對(duì)登錄信息進(jìn)行校驗(yàn),并獲取對(duì)應(yīng)第三方登陸用戶的信息;將第三方用戶信息與本系統(tǒng)用戶進(jìn)行關(guān)聯(lián)。
? ? ? ?下面就以上幾個(gè)步驟的一些關(guān)鍵信息,或者說是我開發(fā)當(dāng)中遇到的問題做一下簡(jiǎn)要的記錄。因?yàn)镕acebook以及Google +第三方登陸都采用的是Auth2技術(shù),因此只會(huì)在具體實(shí)現(xiàn)不同的地方單獨(dú)說明。理解有誤的地方,或者是沒有說全的地方,還請(qǐng)各位諒解~
一 獲得第三方登陸許可認(rèn)證
? ? ? ?在獲取許可上,需要在對(duì)應(yīng)的開發(fā)平臺(tái)上申請(qǐng)登陸接入許可,基本上你可能需要準(zhǔn)備以下幾樣?xùn)|西:
你當(dāng)前需要接入第三方登陸的網(wǎng)址域名(用于第三方平臺(tái)校驗(yàn)是否這個(gè)登錄請(qǐng)求來自于你的網(wǎng)站本身);
給用戶展示的網(wǎng)站logo和文字(用于在第三方登陸的時(shí)候給用戶直觀的展(裝)示(逼));
登陸成功后,跳回的URL(用于獲取并使用登陸用戶的相關(guān)信息);
? ? ? ?申請(qǐng)成功之后,第三方平臺(tái)會(huì)提供給你對(duì)應(yīng)的AppID以及AppSecret,用以后臺(tái)進(jìn)行額外的操作。基本上操作按照官方api的順序一步一步來就可以了惹,這里就不再贅述了~(請(qǐng)掌握基本的英語閱讀能力…)
二 根據(jù)規(guī)范添加頁面登錄樣式和js實(shí)現(xiàn)
? ? ? ?簡(jiǎn)單點(diǎn)講就是在頁面上添加登錄Button,并通過點(diǎn)擊觸發(fā)跳轉(zhuǎn)到第三方的請(qǐng)求。Google+以及Facebook在大體上邏輯一致,在細(xì)節(jié)上實(shí)現(xiàn)略有不同。
? ? ? ?Google+登錄。會(huì)引用自己封裝的js()來實(shí)現(xiàn)登錄操作(gapi),并提供了多種登陸實(shí)現(xiàn)方案可供選擇。這里貼一下,我目前項(xiàng)目中實(shí)現(xiàn)的方案,僅供參考。
1.在對(duì)應(yīng)頁面引用Google第三方j(luò)s。https://apis.google.com/js/api:client.js(這里的js其實(shí)和官方最新的platform.js內(nèi)容是一樣的…吧~)
2.頁面定義Google+登錄的按鈕樣式(這里谷歌有內(nèi)置的規(guī)范按鈕樣式可以直接調(diào)用,不用自己定義)
(id="googleLogin")

3.根據(jù)引用的第三方j(luò)s提供的api,作如下初始化操作:
auth2 = gapi.auth2.init({
client_id: clientID,? ? //第一步申請(qǐng)的時(shí)候,提供給你的appidcookiepolicy: 'single_host_origin',
scope: 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email'//需要獲取的用戶信息領(lǐng)域});
4.初始化后,接著需要對(duì)你定義的按鈕綁定鼠標(biāo)點(diǎn)擊事件,作如下操作:
auth2.attachClickHandler('googleLogin',{},startApp.onSuccess,startApp.onFailure);//googleLogin為按鈕的ID
5.做完這些之后就等用戶點(diǎn)擊(上鉤)啦~這里需要注意下startApp.onSuccess以及startApp.onFailure方法,這里是在谷歌成功登陸之后的回調(diào)函數(shù)。在onSuccess里第三方已經(jīng)登錄并返回,我們已經(jīng)可以根據(jù)接口api獲取想要的用戶信息了,而在onFailure里因?yàn)榈卿浭?,我們可以自定義一些提示信息。
6.等等!上面代碼中的變量都是干嘛用的啊喂~別慌,下面附上完整的js!項(xiàng)目開發(fā)使用了RequireJs,代碼僅供參考!
?View Code
? ? ? ?Facebook登錄。同樣會(huì)調(diào)用自己封裝的js()來實(shí)現(xiàn)登錄操作(FB),實(shí)現(xiàn)步驟基本同Google+登陸類似。
1.在對(duì)應(yīng)頁面引用Facebook第三方j(luò)s。https:?//connect.facebook.net/en_US/sdk.js;
2.頁面定義Facebook登錄的按鈕樣式
(id="fblogin")

3.根據(jù)引用的第三方j(luò)s提供的api,作如下初始化操作:
FB.init ({
? ? appId? ? ? : '#your AppID#',
? ? cookie? ? : true,
? ? xfbml? ? ? : true,
? ? version? ? : 'v2.4'});
4.初始化后,接著需要對(duì)你定義的按鈕綁定鼠標(biāo)點(diǎn)擊登錄事件,作如下操作:
$("#fblogin").click(function (){
? ? FB.login(function(response) {
? ? ? ? statusChangeCallback(response);? //登錄回調(diào)函數(shù)},{scope: 'email'});//需要獲取的信息scope});
5.statusChangeCallback為登錄回調(diào)函數(shù),需要在里面做下登陸返回的相關(guān)操作:
varstatusChangeCallback =function (response){
? ? if(response.status === 'connected') {
? ? ? ? varaccessToken = response.authResponse.accessToken;//取得 accessToken? ?
? ? ? ? FB.api('/me?fields=name,first_name,last_name,email',function(response) {// /me為API指定的調(diào)用方法,用于獲取登陸用戶相關(guān)信息if(response.email!=null){
? ? ? ? ? ? ? ? $.ajax({
? ? ? ? ? ? ? ? ? ? url:"/action.do",
? ? ? ? ? ? ? ? ? ? data:{
? ? ? ? ? ? ? ? ? ? ? ? userName:response.name,
? ? ? ? ? ? ? ? ? ? ? ? firstName:response.first_name,
? ? ? ? ? ? ? ? ? ? ? ? lastName:response.last_name,
? ? ? ? ? ? ? ? ? ? ? ? email:response.email,
? ? ? ? ? ? ? ? ? ? ? ? idToken:accessToken,
? ? ? ? ? ? ? ? ? ? ? ? userType:'2'? ? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? ? dataType:"json",
? ? ? ? ? ? ? ? ? ? tyep:"post",
? ? ? ? ? ? ? ? ? ? success:function(data){
? ? ? ? ? ? ? ? ? ? ? ? if(data.success ==true){
? ? ? ? ? ? ? ? ? ? ? ? ? ? window.location.reload(true);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? alert("XXX.");
? ? ? ? ? ? }
? ? ? ? });
? ? }
};
更詳細(xì)的接口以及實(shí)現(xiàn)請(qǐng)參考最下面提供的官方API鏈接!多讀讀就懂了!
三 后臺(tái)對(duì)登錄信息進(jìn)行校驗(yàn),并獲取對(duì)應(yīng)第三方登陸用戶的信息
在用戶正確的登錄第三方平臺(tái)并進(jìn)行授權(quán)之后,調(diào)用返回函數(shù),這時(shí)需要對(duì)用戶的登錄信息和狀態(tài)進(jìn)行確認(rèn)!這里非常關(guān)鍵,因?yàn)橐_保用戶的確是從對(duì)應(yīng)第三方平臺(tái)登錄,而不是隨隨便便敲一個(gè)URL就能讓請(qǐng)求通過了。所以我們需要第三方平臺(tái)提供的access_token值,根據(jù)約定好的校驗(yàn)規(guī)則進(jìn)行校驗(yàn),放行校驗(yàn)通過的登陸請(qǐng)求。
? ? ? ?由于驗(yàn)證信息涉及到app的隱私信息,以及確保驗(yàn)證不會(huì)被人為的篡改,因此需要在服務(wù)器后端進(jìn)行token的驗(yàn)證。
參見第二條相關(guān)js實(shí)現(xiàn),在第三方調(diào)用返回函數(shù)之后,代碼中會(huì)進(jìn)行ajax請(qǐng)求,調(diào)用后臺(tái)的對(duì)應(yīng)接口?/action.do,來在后臺(tái)進(jìn)行access_token的正確性判斷。
? ? ? ?后臺(tái)會(huì)根據(jù)登陸的第三方類型,進(jìn)行https請(qǐng)求驗(yàn)證,來確保用戶登陸的信息無誤。
Google+的token驗(yàn)證地址:https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XXX
? ? ? ?Google+的token驗(yàn)證通過返回的Json格式(校驗(yàn)aud是否與后臺(tái)保存的AppId匹配):
{
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"email": "billd1600@gmail.com",
"at_hash": "X_B3Z3Fi4udZ2mf75RWo3w",
"email_verified": "true",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953"
}
Facebook的token驗(yàn)證地址(%7C為encode的 '|'符號(hào)):https://graph.facebook.com/debug_token?access_token={Your AppId}%7C{Your AppSecret}&input_token=XXX
? ? ? ?Facebook的token驗(yàn)證通過返回的Json格式("is_valid": true):
{
? ? "data": {
? ? ? ? "app_id": 000000000000000,
? ? ? ? "application": "Social Cafe",
? ? ? ? "expires_at": 1352419328,
? ? ? ? "is_valid":true,
? ? ? ? "issued_at": 1347235328,
? ? ? ? "scopes": [
? ? ? ? ? ? "email",
? ? ? ? ? ? "publish_actions"? ? ? ? ],
? ? ? ? "user_id": 1207059? ? }
}
因?yàn)檫@里后臺(tái)采用JAVA開發(fā),在驗(yàn)證地址為HTTPS請(qǐng)求驗(yàn)證的時(shí)候,后臺(tái)利用HttpClient請(qǐng)求的時(shí)候涉及到證書驗(yàn)證的問題,所以這里采用了 @rongyongfeikai2同學(xué)的方法:《JAVA利用HttpClient進(jìn)行POST請(qǐng)求(HTTPS)》,有需求的可以參考借鑒。
? ? ? ?后臺(tái)根據(jù)對(duì)應(yīng)官方的api文檔的token校驗(yàn)方式,對(duì)獲取到的token進(jìn)行校驗(yàn)。如果請(qǐng)求的驗(yàn)證地址返回的信息為校驗(yàn)通過,則可以進(jìn)行后面的操作了。
四 將第三方用戶信息與本系統(tǒng)用戶進(jìn)行關(guān)聯(lián)
? ? ? ?在進(jìn)行前端js請(qǐng)求的時(shí)候,對(duì)應(yīng)平臺(tái)的api接口會(huì)獲取到用戶的信息(參照上述代碼)。與此同時(shí),在進(jìn)行用戶token校驗(yàn)的時(shí)候,返回的對(duì)應(yīng)json對(duì)象中也會(huì)包含對(duì)應(yīng)的用戶信息,這些信息可以在后臺(tái)進(jìn)行解析和獲取,詳細(xì)的數(shù)據(jù)結(jié)構(gòu)可以參考官方文檔。為了確保用戶信息不會(huì)被中途截?cái)啻鄹?,可以在后臺(tái)進(jìn)行數(shù)據(jù)獲取。
? ? ? ?在獲取到第三方登錄用戶的信息之后,就可以與本系統(tǒng)的賬戶進(jìn)行匹配操作了。之后的操作存在幾種不同的方式類型,對(duì)于本系統(tǒng)來講,采用的是以下鑒定流程。

后敘
? ? ? ?以上為目前我們系統(tǒng)中的第三方登錄的基本實(shí)現(xiàn)方案,也許并不太完整(畢竟基本上之前沒怎么涉及過…),但是希望其中的涉及到的點(diǎn)能夠幫助到大家,也希望大家能指出寫的不對(duì)的地方,并多多包涵哈。
文末也給大家,分享主要有C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協(xié)程,DPDK技術(shù),面試技巧方面的資料技術(shù)討論。
感興趣的朋友可以加群:812855908