[英]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信息(如此處所示 )。
我有兩個問題:
OAuthException
。 但有沒有更好的方法來檢測到期? 我不想 我想在服務方法的實現中實現以下方案:
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的通信以獲取訪問令牌,這是同步執行的。
最后的問題:
我不知道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令牌並不是您可以等待響應的請求,它實際上會觸發最終導致單獨獲取請求的內容 請注意,盡管上圖是針對用戶首次登錄時的情況,但大致在失敗的呼叫中會發生相同的序列,但它會從重定向開始。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.