[Facebook API] Facebook Login 並取得用戶基本資料,使用 Javascript SDK

Facebook Login and get user's basic profile using Javascript SDK

 

前言

最近工作需要抓取Facebook用戶的個資,於是這兩天又重新研究起Facebook API

雖然之前已寫過Facebook Login的Javascript範例程式碼:[FB/Google] 社群帳號登入,使用Javascript SDK的Sample Code

而且功能運作都正常,但我發現程式如果重複呼叫FB.login()或FB.api(),在瀏覽器的Console會發生以下錯誤

You are overriding current access token, that means some other app is expecting different access token and you will probably break things. Please consider passing access_token directly to API parameters instead of overriding the global settings.

奇怪的是我使用Javascript SDK,明明它會自動處理access_token(存取權杖),結果錯誤訊息還叫我傳遞access_token (黑人問號??

網頁版「Facebook 登入」的存取權杖:https://developers.facebook.com/docs/facebook-login/web/accesstokens/

Stackoverflow:Should I pass access token when using FB.api()?

Graph API Request:https://developers.facebook.com/docs/javascript/reference/FB.api/

瀏覽器Console裡的錯誤訊息雖然不理它並不影響程式運作(可能我寫的程式功能簡單,才只有登入&撤銷App?),但心裡還是覺得毛毛的,於是我試出以下兩種解決辦法:

1.每次呼叫FB.login()、FB.api()前,都先呼叫FB.getLoginStatus()檢查用戶和你的App授權&登入狀態

Login Status.:https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus

然後在用戶撤銷你的App後還要再呼叫一次FB.getLoginStatus(),並且最後一個參數傳入 true 清除cache

要注意不能每次呼叫FB.getLoginStatus()都傳遞true參數來清除cache,除了上圖說的會降低應用程式效能外,且有可能會再度發生下面的錯誤訊息

You are overriding current access token, that means some other app is expecting different access token and you will probably break things. Please consider passing access_token directly to API parameters instead of overriding the global settings.

 

2.第二種解決辦法就是每次呼叫FB.login()、FB.api()之前或之後,利用Javascript程式碼重新整理頁面,目的讓access_token更新

window.location.href = window.location.href;
<!--↑挑一個執行↓-->
window.location.reload(); 

但是第二種辦法使用者體驗很糟糕,網頁可能要頻繁重新整理,,所以我選擇第一種解決辦法為主

前置作業

FB應用程式設定的介面改版速度很快,我若現在辛苦擷圖寫完功能說明,可能幾個月後又被官方推翻

所以這裡我簡單介紹一下就好,剩下其他功能眉眉角角的請看倌們自行探索XD

先進入facebook for developers:https://developers.facebook.com/apps/

準備建立一個應用程式

由於採用Javascript SDK,只要擁有應用程式編號(appId)即可,點擊「應用程式編號」複製起來待會要使用

其實左下角的產品紅框處,應該要手動加入一個「Facebook登入」或點擊Facebook 登入的「設定」

但我發現不知道是不是應用程式未上線&本機測試關係,現在把應用程式編號貼到自己工作專案上就可以跑了XD

以下是程式碼

說明在註解裡

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <div>
        Facebook登入並取得用戶姓名、email:<input type="button" value="Facebook登入" onclick="FBLogin();" />
    </div>
    <div>
        <!--留意用戶的此頁,你的App會被移除:https://www.facebook.com/settings?tab=applications-->
        用戶刪除授權的App(撤銷登入):<input type="button" value="Disconnect App" onclick="Del_FB_App()" />
    </div>
    <!--顯示用戶的姓名、email↓-->
    <div id="content"></div>
    <script type="text/javascript">
        //應用程式編號,進入 https://developers.facebook.com/apps/ 即可看到
        let FB_appID = "你的應用程式編號";

        

        // Load the Facebook Javascript SDK asynchronously
        (function (d, s, id) {
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) return;
            js = d.createElement(s); js.id = id;
            js.src = "https://connect.facebook.net/en_US/sdk.js";
            fjs.parentNode.insertBefore(js, fjs);
        }(document, 'script', 'facebook-jssdk'));

        window.fbAsyncInit = function () {
            FB.init({
                appId: FB_appID,//FB appID
                cookie: true,  // enable cookies to allow the server to access the session
                xfbml: true,  // parse social plugins on this page
                version: 'v4.0' // use graph api version
            });
            FB.AppEvents.logPageView();

        };

        //使用自己客製化的按鈕來登入
        function FBLogin() {
            FB.getLoginStatus(function (res) {
                console.log(`status:${res.status}`);//Debug

                if (res.status === "connected") { 
                    let userID = res["authResponse"]["userID"];
                    console.log("用戶已授權您的App,用戶須先revoke撤除App後才能再重新授權你的App");
                    console.log(`已授權App登入FB 的 userID:${userID}`);
                    GetProfile();
                } else if (res.status === 'not_authorized' || res.status === "unknown") {
                    //App未授權或用戶登出FB網站才讓用戶執行登入動作
                    FB.login(function (response) {

                        //console.log(response); //debug用
                        if (response.status === 'connected') {
                            //user已登入FB
                            //抓userID
                            let userID = response["authResponse"]["userID"];
                            console.log(`已授權App登入FB 的 userID:${userID}`);
                            GetProfile();

                        } else {
                            // user FB取消授權
                            alert("Facebook帳號無法登入");
                        }
                        //"public_profile"可省略,仍然可以取得name、userID
                    }, { scope: 'email' }); 
                }
            });


        }
    </script>
    <script type="text/javascript">
        //取得用戶姓名、email
        function GetProfile() {
            document.getElementById('content').innerHTML = "";//先清空顯示結果

            //FB.api()使用說明:https://developers.facebook.com/docs/javascript/reference/FB.api
            //取得用戶個資
            FB.api("/me", "GET", { fields: 'last_name,first_name,name,email' }, function (user) {
                //user物件的欄位:https://developers.facebook.com/docs/graph-api/reference/user
                if (user.error) {
                    console.log(response);
                } else {
                    
                    document.getElementById('content').innerHTML = JSON.stringify(user);
                }
            });

        }
    </script>




    <!--有些網站會做帳號和user FB帳號的綁定/解除綁定,或你想讓使用者刪除你的FB App,讓使用者下次可以切換不同FB帳號登入你的網站-->
    <!--下面程式碼派得上用場-->
    <script type="text/javascript">

        //刪除使用者已授權你的FB App,好讓使用者下次重新授權你的FB App
        //參考:https://stackoverflow.com/questions/6634212/remove-the-application-from-a-user-using-graph-api/7741978#7741978
        //https://stackoverflow.com/questions/9050190/facebook-api-sdk-revoke-access
        function Del_FB_App() {

            FB.getLoginStatus(function (response) {//取得目前user是否登入FB網站
                //debug用
                console.log(response);
                if (response.status === 'connected') {
                    //抓userID
                    //let userID = response["authResponse"]["userID"];


                    FB.api("/me/permissions", "DELETE", function (response) {
                        console.log("刪除結果");
                        console.log(response); //gives true on app delete success
                        //最後一個參數傳遞true避免cache
                        FB.getLoginStatus(function (res) { }, true);//強制刷新cache避免login status下次誤判
                        
                    });

                } else { 
                    console.log("無法刪除FB App");
                }
            });
             
        } 
    </script> 
</body>
</html>

程式執行結果

需留意userID,每個App產生出來的userID會不一樣,userID無法跨App之間使用

用戶授權你的App後,他個人的此頁面:https://www.facebook.com/settings?tab=applications ,就會出現你的App

如果用戶「撤銷登入」的話↓

「要求和撤銷權限」的官網說明:https://developers.facebook.com/docs/facebook-login/permissions/requesting-and-revoking

官方也有Facebook Login with Javascript 的範例程式碼:搭配 JavaScript SDK 的網頁版「Facebook 登入」

↑但本人自認我寫的登入功能比較完整XD

 

Facebook的設定

只要呼叫過一次Facebook API,剛剛的應用程式設定畫面,就會自動加入一個「Facebook 登入」的產品

 FB.login()可以傳遞的scope參數(要求用戶提供哪種個資給你的App)在這頁↓ 少得可憐,只有預設的姓名和email

可以申請哪些scope權限的說明網址在這↓

權限參考資料 - Facebook 登入:https://developers.facebook.com/docs/facebook-login/permissions

接著便可以把上面那些關鍵字輸入查詢,要求審查額外權限↓

應用程式審查的說明

官方有提供審查範例:Sample App Review Submission for Facebook Login

最終,應用程式要切換成上線模式的話,有幾個欄位必須填寫

「應用程式網域」沒填的話,雖然仍舊可以成功切換成「上線狀態」,但程式執行時期會發生錯誤↓

 

其他補充資料

登入安全性:https://developers.facebook.com/docs/facebook-login/security

↑ 一些應用程式安全性設定相關說明

「Facebook 登入」的權限:https://developers.facebook.com/docs/facebook-login/permissions/overview

 

 

 

猜你也感興趣的文章

一目瞭然!Line vs Facebook vs Goolge,比較各自的API可以取得的用戶個資