2010-10-23 65 views
2

我想如果我們使用REST或圖形API調用Facebook,我們會知道它是否是假的,因爲它會回來說虛假的會話/ auth_token/access_token。但是如果我們顯示自己的數據庫信息(例如用戶的「最喜歡的產品列表」),那麼我們不會打電話給Facebook,而是顯示我們的數據庫的數據。我們如何知道它確實是用戶,而不是有人僞造cookie?如果我們的網站看到Facebook上登錄的用戶在cookie中有用戶ID 678678678,我們如何知道這個cookie不是僞造的?

+0

要在這裏downvoted每一個答案的人:爲什麼呢? – Yuliy 2010-10-24 16:37:38

+0

請參閱下面的答案。其他人都錯了。 :/ – 2010-10-24 16:43:44

回答

2

當您閱讀facebook的cookie時,它包含一個名爲'sig'的值。有了這個值,其他的cookie值和你的應用程序祕密,你可以散列cookie的內容並根據sig驗證它。如果它們匹配,那麼cookie是有效的。你可以相信這個結果,因爲只有你和Facebook可以訪問應用程序的祕密。這裏是Facebook的PHP SDK如何做的例子。任何可敬的Facebook SDK都會在內部完成這一切。

/** 
    * Validates a session_version=3 style session object. 
    * 
    * @param Array $session the session object 
    * @return Array the session object if it validates, null otherwise 
    */ 
    protected function validateSessionObject($session) { 
    // make sure some essential fields exist 
    if (is_array($session) && 
     isset($session['uid']) && 
     isset($session['access_token']) && 
     isset($session['sig'])) { 
     // validate the signature 
     $session_without_sig = $session; 
     unset($session_without_sig['sig']); 
     $expected_sig = self::generateSignature(
     $session_without_sig, 
     $this->getApiSecret() 
    ); 
     if ($session['sig'] != $expected_sig) { 
     self::errorLog('Got invalid session signature in cookie.'); 
     $session = null; 
     } 
     // check expiry time 
    } else { 
     $session = null; 
    } 
    return $session; 
    } 

這裏是C#一樣的東西(Facebook C# SDK):

/// <summary> 
    /// Validates a session_version=3 style session object. 
    /// </summary> 
    /// <param name="session">The session to validate.</param> 
    protected override void ValidateSessionObject(FacebookSession session) 
    { 
     if (session == null) 
     { 
      return; 
     } 

     var signature = this.GenerateSignature(session); 
     if (session.Signature == signature.ToString()) 
     { 
      return; 
     } 

     session = null; 
    } 

    /// <summary> 
    /// Generates a MD5 signature for the facebook session. 
    /// </summary> 
    /// <param name="session">The session to generate a signature.</param> 
    /// <returns>An MD5 signature.</returns> 
    /// <exception cref="System.ArgumentNullException">If the session is null.</exception> 
    /// <exception cref="System.InvalidOperationException">If there is a problem generating the hash.</exception> 
    protected override string GenerateSignature(FacebookSession session) 
    { 
     var args = session.Dictionary; 
     StringBuilder payload = new StringBuilder(); 
     var parts = (from a in args 
        orderby a.Key 
        where a.Key != "sig" 
        select string.Format(CultureInfo.InvariantCulture, "{0}={1}", a.Key, a.Value)).ToList(); 
     parts.ForEach((s) => { payload.Append(s); }); 
     payload.Append(this.ApiSecret); 
     byte[] hash = null; 
     using (var md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create()) 
     { 
      if (md5 != null) 
      { 
       hash = md5.ComputeHash(Encoding.UTF8.GetBytes(payload.ToString())); 
      } 
     } 

     if (hash == null) 
     { 
      throw new InvalidOperationException("Hash is not valid."); 
     } 

     StringBuilder signature = new StringBuilder(); 
     for (int i = 0; i < hash.Length; i++) 
     { 
      signature.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture)); 
     } 

     return signature.ToString(); 
    } 
-1

不要將它存儲在cookie中。把它放在會話變量中,這樣你就可以控制

+0

我認爲當用戶向我們的Web服務器發出請求時,沒有任何狀態 - 所有這一切都證實用戶確實在舊REST API和圖形API中的Cookie – 2010-10-23 05:51:43

-1

不要把用戶ID放在cookie中。會話cookie應該只是一個隨機數字,映射到服務器端會話數據庫中的記錄。與該會話關聯的任何數據僅存儲在服務器端。

這樣,爲了僞造會話,攻擊者必須猜測當時實際使用的隨機數。鑑於有很多隨機數字和會話過期,這幾乎是不可能的。

+0

中,在單擊「用Facebook登錄「,用戶ID總是在Facebook爲我們的網站設置的Cookie中(或者是Cookie的一部分)使用... – 2010-10-23 06:08:41

+0

你說過你想顯示自己的數據庫的數據。根據任何Facebook cookies不要這樣做。只信任你自己的cookies。 – Thilo 2010-10-23 06:12:25

0

你可以信任的唯一事情是session_key老REST API和access_token的圖形API。一旦你得到它,將它傳遞給服務器端與您的數據重新調整請求。在服務器端調用facebook api並獲取當前用戶標識。一旦你得到了userid,你可以將它存儲在一個會話中,並在以後使用它。

-1

這裏有幾種方法。低效:每當你執行一個認證的操作時,抓住FB cookie並使用其中的數據來做一個虛擬的API調用,看看訪問令牌是否有效,並匹配用戶(即抓/我?fields = id )。

效率更高:當您第一次看到用戶的FB cookie時,將該cookie存儲在用戶的服務器端會話中(在Cookie中傳遞給客戶端的會話ID足夠難猜測) )。

另一種方法,並不需要服務器端會話狀態:第一次看到用戶的FB cookie時,HMAC只使用您的服務器使用祕密的cookie,並將結果散列存儲在cookie中。然後你可以檢查FB cookie是否有一個有效的散列,如果有的話,你相信它。否則,你會回到驗證。

相關問題