簡述
最近項目中有關於第三方登陸的需求,第三方Facebook以及Google +登錄。
正好這幾天把這個需求做得差不多了,收個尾,作為一個這方面之前基本從未涉及的小白,總結下開發流程以及過程中遇到的一些問題。希望能對大家有所幫助。
基本上,目前互聯網上的涉及到第三方登錄采用的都為OAuth認證方式,相關原理以及實現方法相關的可以網上搜索查看。不過涉及到Facebook以及Google +的登陸,最大的問題是這兩個網站在牆外,想翻牆找資料比較費勁,奈何國內這方面的資料也不是很齊全,翻到的官方的文檔又全是英文的,閱讀無能~
第三方登陸簡單可以分為以下幾個步驟,分別是:獲得第三方登陸許可認證;根據規范添加頁面登錄樣式和js實現,跳轉到第三方登陸頁面登陸並獲取授權后,返回原指定頁面(或請求);后台對登錄信息進行校驗,並獲取對應第三方登陸用戶的信息;將第三方用戶信息與本系統用戶進行關聯。
下面就以上幾個步驟的一些關鍵信息,或者說是我開發當中遇到的問題做一下簡要的記錄。因為Facebook以及Google +第三方登陸都采用的是Auth2技術,因此只會在具體實現不同的地方單獨說明。理解有誤的地方,或者是沒有說全的地方,還請各位諒解~
一 獲得第三方登陸許可認證
在獲取許可上,需要在對應的開發平台上申請登陸接入許可,基本上你可能需要准備以下幾樣東西:
- 你當前需要接入第三方登陸的網址域名(用於第三方平台校驗是否這個登錄請求來自於你的網站本身);
- 給用戶展示的網站logo和文字(用於在第三方登陸的時候給用戶直觀的展(裝)示(逼));
- 登陸成功后,跳回的URL(用於獲取並使用登陸用戶的相關信息);
申請成功之后,第三方平台會提供給你對應的AppID以及AppSecret,用以后台進行額外的操作。基本上操作按照官方api的順序一步一步來就可以了惹,這里就不再贅述了~(請掌握基本的英語閱讀能力…)
二 根據規范添加頁面登錄樣式和js實現
簡單點講就是在頁面上添加登錄Button,並通過點擊觸發跳轉到第三方的請求。Google+以及Facebook在大體上邏輯一致,在細節上實現略有不同。
Google+登錄。會引用自己封裝的js(<script src="https://apis.google.com/js/platform.js" defer async="true"></script>)來實現登錄操作(gapi),並提供了多種登陸實現方案可供選擇。這里貼一下,我目前項目中實現的方案,僅供參考。
1.在對應頁面引用Google第三方js。https://apis.google.com/js/api:client.js(這里的js其實和官方最新的platform.js內容是一樣的…吧~)
2.頁面定義Google+登錄的按鈕樣式(這里谷歌有內置的規范按鈕樣式可以直接調用,不用自己定義)
(id="googleLogin")
3.根據引用的第三方js提供的api,作如下初始化操作:
auth2 = gapi.auth2.init({ client_id: clientID, //第一步申請的時候,提供給你的appid cookiepolicy: 'single_host_origin', scope: 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email' //需要獲取的用戶信息領域 });
4.初始化后,接着需要對你定義的按鈕綁定鼠標點擊事件,作如下操作:
auth2.attachClickHandler('googleLogin',{},startApp.onSuccess,startApp.onFailure); //googleLogin為按鈕的ID
5.做完這些之后就等用戶點擊(上鈎)啦~這里需要注意下startApp.onSuccess以及startApp.onFailure方法,這里是在谷歌成功登陸之后的回調函數。在onSuccess里第三方已經登錄並返回,我們已經可以根據接口api獲取想要的用戶信息了,而在onFailure里因為登錄失敗,我們可以自定義一些提示信息。
6.等等!上面代碼中的變量都是干嘛用的啊喂~別慌,下面附上完整的js!項目開發使用了RequireJs,代碼僅供參考!
define("glogin", ['google', 'jquery'], function(google, $) {
var startApp = {};
var googleUser = {};
var clientID = "#your AppID#";
startApp.onSuccess = function(googleUser) {
var profile = googleUser.getBasicProfile();
var authProfile = googleUser.getAuthResponse();
var userName = profile.getName();
var userImage = profile.getImageUrl();
var userEmail = profile.getEmail();
var idToken = authProfile.id_token;
var flag = true;
if (userEmail && idToken) {
$.ajax({
url: "/action.do",
data: {
userName: userName,
firstName: userName,
lastName: userName,
email: userEmail,
idToken: idToken,
userType: '3'
},
dataType: "json",
tyep: "post",
success: function(data) {
if (data.success == true) {
window.location.reload(true);
} else {
flag = false;
}
}
});
}
if (!flag) {
alert.alert("XXX.");
}
};
startApp.onFailure = function(error) {
console.log(error);
alert.alert("XXX.");
};
startApp.init = function() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: clientID,
cookiepolicy: 'single_host_origin',
scope: 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email'
});
auth2.attachClickHandler('googleLogin', {}, startApp.onSuccess, startApp.onFailure);
});
};
return startApp;
});
require(["glogin"], function(main) {
main.init();
});
Facebook登錄。同樣會調用自己封裝的js(<script src="https: //connect.facebook.net/en_US/sdk.js" defer async="true"></script>)來實現登錄操作(FB),實現步驟基本同Google+登陸類似。
1.在對應頁面引用Facebook第三方js。https: //connect.facebook.net/en_US/sdk.js;
2.頁面定義Facebook登錄的按鈕樣式
(id="fblogin")
3.根據引用的第三方js提供的api,作如下初始化操作:
FB.init ({ appId : '#your AppID#', cookie : true, xfbml : true, version : 'v2.4' });
4.初始化后,接着需要對你定義的按鈕綁定鼠標點擊登錄事件,作如下操作:
$("#fblogin").click(function (){
FB.login(function(response) {
statusChangeCallback(response); //登錄回調函數
},{scope: 'email'}); //需要獲取的信息scope
});
5.statusChangeCallback為登錄回調函數,需要在里面做下登陸返回的相關操作:
var statusChangeCallback = function (response){ if (response.status === 'connected') { var accessToken = response.authResponse.accessToken; //取得 accessToken FB.api('/me?fields=name,first_name,last_name,email', function(response) { // /me為API指定的調用方法,用於獲取登陸用戶相關信息 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."); } }); } };
更詳細的接口以及實現請參考最下面提供的官方API鏈接!多讀讀就懂了!
三 后台對登錄信息進行校驗,並獲取對應第三方登陸用戶的信息
在用戶正確的登錄第三方平台並進行授權之后,調用返回函數,這時需要對用戶的登錄信息和狀態進行確認!這里非常關鍵,因為要確保用戶的確是從對應第三方平台登錄,而不是隨隨便便敲一個URL就能讓請求通過了。所以我們需要第三方平台提供的access_token值,根據約定好的校驗規則進行校驗,放行校驗通過的登陸請求。
由於驗證信息涉及到app的隱私信息,以及確保驗證不會被人為的篡改,因此需要在服務器后端進行token的驗證。
參見第二條相關js實現,在第三方調用返回函數之后,代碼中會進行ajax請求,調用后台的對應接口 /action.do,來在后台進行access_token的正確性判斷。
后台會根據登陸的第三方類型,進行https請求驗證,來確保用戶登陸的信息無誤。
Google+的token驗證地址:https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XXX
Google+的token驗證通過返回的Json格式(校驗aud是否與后台保存的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驗證地址(%7C為encode的 '|'符號):https://graph.facebook.com/debug_token?access_token={Your AppId}%7C{Your AppSecret}&input_token=XXX
Facebook的token驗證通過返回的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 } }
因為這里后台采用JAVA開發,在驗證地址為HTTPS請求驗證的時候,后台利用HttpClient請求的時候涉及到證書驗證的問題,所以這里采用了 @rongyongfeikai2同學的方法:《JAVA利用HttpClient進行POST請求(HTTPS)》,有需求的可以參考借鑒。
后台根據對應官方的api文檔的token校驗方式,對獲取到的token進行校驗。如果請求的驗證地址返回的信息為校驗通過,則可以進行后面的操作了。
四 將第三方用戶信息與本系統用戶進行關聯
在進行前端js請求的時候,對應平台的api接口會獲取到用戶的信息(參照上述代碼)。與此同時,在進行用戶token校驗的時候,返回的對應json對象中也會包含對應的用戶信息,這些信息可以在后台進行解析和獲取,詳細的數據結構可以參考官方文檔。為了確保用戶信息不會被中途截斷篡改,可以在后台進行數據獲取。
在獲取到第三方登錄用戶的信息之后,就可以與本系統的賬戶進行匹配操作了。之后的操作存在幾種不同的方式類型,對於本系統來講,采用的是以下鑒定流程。
|
|
后敘
以上為目前我們系統中的第三方登錄的基本實現方案,也許並不太完整(畢竟基本上之前沒怎么涉及過…),但是希望其中的涉及到的點能夠幫助到大家,也希望大家能指出寫的不對的地方,並多多包涵哈。
PS:第一次寫博客,不知道該怎么下手,明明腦子里想的很多,一寫動筆就不知道該寫什么好惹……
以下為開發過程中參考的文章地址,有需求的朋友可以自行點擊查閱!
Google+登錄api:https://developers.google.com/identity/sign-in/web/devconsole-project
Google+自定義button:https://developers.google.com/identity/sign-in/web/build-button
Google+ token驗證:https://developers.google.com/identity/sign-in/web/backend-auth
Facebook登錄api:https://developers.facebook.com/docs/facebook-login?locale=zh_CN
Facebooktoken驗證 api:https://developers.facebook.com/docs/facebook-login/access-tokens/debugging-and-error-handling
Facebook token驗證解決方案:http://stackoverflow.com/questions/19359868/how-would-you-perform-debug-token-call-using-facebook-php-sdk
后台https地址請求解決方法:http://blog.csdn.net/rongyongfeikai2/article/details/41659353

