簡體   English   中英

如何在處理使用Facebook API調用的服務方法時透明地更新Facebook訪問令牌?

[英]How to transparently renew the Facebook access token while processing a service method which uses Facebook API calls?

我有一個在IIS 7.5和VS 2010中運行的WCF服務。此服務有一些方法在內部使用Facebook C#SDK (版本4.1,而不是最新版本),以便從/向Facebook執行一些GET和POST。 由於Facebook將很快刪除 offline_access我必須處理訪問令牌過期的情況。

我已經了解了執行身份驗證的方式(為了獲取代碼並在獲取訪問令牌之后),以便使用Graph API獲取Facebook信息(如此處所示 )。

我有兩個問題:

  • 調用我的服務方法並從數據庫中檢索相應用戶的令牌時,是否有辦法知道訪問令牌是否已過期?
    我已經讀過 ,當執行Facebook API調用並且訪問令牌過期時,會拋出以下異常: OAuthException 但有沒有更好的方法來檢測到期? 我不想
    1. 調用Facebook API
    2. 處理異常
    3. 最后更新訪問令牌
    4. 使用新的訪問令牌重復初始調用。
  • 是否可以透明地更新用戶的訪問令牌(也將其存儲在數據庫中)並繼續處理服務方法? 資源中,缺少重要的(“更新訪問令牌”)部分(聲明為[todo])

我想在服務方法的實現中實現以下方案:

sc = SocialNetworkAccountDao.GetByUser(user)

isExpired = call method to check if the sc.token is expired.

if (isExpired)

{

  newToken = call method for getting new access token

  sc.token = newToken;

  SocialNetworkAccount.Update(sc);

}

Facebook = new Facebook (sc.token)

Facebook.Post( ..... )

--

QAuth對話通信的過程是異步的(執行重定向),並且與訪問令牌url的通信以獲取訪問令牌,這是同步執行的。

最后的問題:

  • 有沒有辦法讓服務方法等待我們從Facebook請求/回調中檢索的新訪問令牌,以便稍后繼續使用新的訪問令牌?

我不知道C#SDK,但所有facebook SDK基本上只是http請求圖表不同網址的包裝。

如果您使用服務器端身份驗證流程,那么您應該獲得一個長期存在的令牌(大約60天),並且您獲得它的到期時間,當它到期時您需要重新驗證用戶,沒有辦法擴展令牌。

客戶端身份驗證返回一個短期令牌(大約2小時),但您可以使用提供的新端點 facebook來替換“offline_token”。 您只能將其用於仍然有效的訪問令牌。

此外,無論如何,當您獲得訪問令牌時,您始終會獲得“到期”時間,除非它是沒有到期日期的應用程序令牌。

在任何一種情況下,如果您獲得一個長期存在的令牌,您可以將其存儲在數據庫中並在服務器端使用它,但請注意,由於多種原因令牌仍然無效。

您還可以使用處理無效和過期訪問令牌的官方文檔。 如果C#SDK不適合您,那么您可能希望自己實現它,為了您自己的需要,應該非常簡單。

您應該將c#sdk更新到最新版本 - 它們會隨着時間的推移解決很多問題。

續訂令牌
這是我們處理續訂調用的代碼(c#sdk ver 6.0.16,但這也適用於早期版本):

    /// <summary>
    /// Renews the token.. (offline deprecation)
    /// </summary>
    /// <param name="existingToken">The token to renew</param>
    /// <returns>A new token (or the same as existing)</returns>
    public static string RenewToken(string existingToken)
    {
        var fb = new FacebookClient();
        dynamic result = fb.Get("oauth/access_token", 
                                new {
                                    client_id         = FACEBOOK_APP_ID,
                                    client_secret     = FACEBOOK_APP_SECRET,
                                    grant_type        = "fb_exchange_token",
                                    fb_exchange_token = existingToken
                                });

        return result.access_token;            
    }

Facebook表示新令牌可能是相同的(但延長到期時間)或全新的令牌,因此如果需要,您應該在邏輯中處理它。

根據Facebook的說法,你應該每天更新一次。 https://developers.facebook.com/roadmap/offline-access-removal/

我們在上次“Facebook更新”完成時保留時間戳,如果該時間超過24小時並且用戶正在訪問我們的應用程序,我們將在后台進行更新令牌。 (我們還會更新其他數據,姓名,電子郵件和其他我們需要的東西)

顯然,它不會每天調用一次,而是每個令牌調用一次。

Facebook不會讓你續訂一個長期存在的令牌。 請參閱脫機訪問刪除頁面上的 “方案4:”

澄清一下:短命代幣來自客戶,長壽代幣來自服務器端。

簡而言之,當用戶訪問您的應用程序時,使用客戶端的SDK獲取一個新的短期令牌將其發送到服務器,並使用您的服務器擴展它以使其成為一個長期存儲並存儲,因此您獲得從那時起60天。

處理過期時間
在我們當前的用法中,我們不需要保持到期時間的跟蹤,因為所有訪問都是從檢查它的客戶端開始的,但在相同的代碼訪問結果中result.access_token它可以訪問result.expires ,它返回秒數留在新獲得的令牌上(應該接近5密爾=> 60天))。

在任何情況下,我都不確定是否有辦法從令牌獲取到期時間而不再調用auth進程。 我知道Facebook調試器會返回這個,但這並沒有真正幫助..

續訂無效令牌
這將無效 ,您將在嘗試續訂過期/無效令牌時獲得此處所述的任何錯誤。
請記住在續訂到期之前調用續訂並記住,當您在過期(或任何其他類型的無效)上調用續訂時,您將收到錯誤並需要處理它(我們在我粘貼的代碼之外處理它)。

到期的時間

簡短的回答:你得到秒數,直到它過期,但c#api似乎不暴露它。

根據這個 facebook文檔,當你獲得令牌時,你得到令牌到期時的秒數。 文檔將響應格式列為:

access_token=USER_ACESS_TOKEN&expires=NUMBER_OF_SECONDS_UNTIL_TOKEN_EXPIRES 

這得到了Ouath 2的RFC草案的支持,該草案稱響應應該包含到期時間。

不幸的是,它與此處所述的C#SDK文檔直接相矛盾

如果沒有向Facebook發出請求,則無法確定訪問令牌是否過期。 因此,您必須始終假設在向Facebook發出請求時,訪問令牌可能已過期。

這不是真的。 如果查看c#SDK源代碼,sdk為OAuth響應創建的對象顯式包含(不幸的是作為私有變量)以下代碼

    /// <summary>
    /// Date and Time when the access token expires.
    /// </summary>
    private readonly DateTime _expires;

所以它有數據,但由於某種原因不暴露它(至少在那里,我沒有進一步看)。 我要說要么更多地挖掘庫,看看它是否暴露在某個地方,在github上分叉和修補它(我相信這是一行更改),或者使用反射來讀取你自己代碼中的私有變量。

繼續處理服務方法並更新令牌

簡短的回答:也許吧。 如果您知道令牌已過期,您可以在請求之前明顯地獲得新令牌。

如果你沒有,那么你可以,但你需要處理你的請求失敗。 從理論上講,這並不意味着您需要處理異常,只需查看http狀態代碼(400個中的一個可能是403禁止)但是C#的webrequest方法將非200狀態c作為引發異常的事件進行處理。 由於API使用此機制進行調用,因此只有在失敗時才會出現異常。

有沒有辦法使服務方法等待我們從中檢索的新訪問令牌

當然,在你處理異常之后。

一旦發生這種情況,異步,您將獲得一個新的身份驗證令牌。 因此,您可以在捕獲異常后等待一段時間,檢查是否為該用戶獲取了新令牌,如果是,則重試。 如果繼續等待和檢查。 確保您有最大重試次數和最長等待時間。 拉動數據庫以檢查更改是有點低效的,因此您可能希望選擇仔細檢查更改的時間間隔,並可能使其以指數方式退回

另一個更有效的(對於單個服務器),但是復雜的方式是讓系統通過auth令牌獲取回調引發事件並讓重試邏輯監聽這些事件。

當您的代碼因令牌過期而獲得異常時,在catch塊中創建一個函數,該函數將重做請求,然后將其作為事件偵聽器添加到auth事件中。 讓函數檢查事件是否為請求事件的用戶提供了新的身份驗證令牌,如果是,請發出請求。 再次,記住要有最大重試次數。

實際上不可能使用async / await或類似的東西等待您的新令牌的請求完成。 問題是,刷新API令牌並不是您可以等待響應的請求,它實際上會觸發最終導致單獨獲取請求的內容
Facebook API請求 請注意,盡管上圖是針對用戶首次登錄時的情況,但大致在失敗的呼叫中會發生相同的序列,但它會從重定向開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM