2011-09-22 83 views
3

我有一個以GWT製作的網頁。在那裏我使用所有的登錄Facebook的東西與操縱gwtfb庫,一切正常。現在遷移到oauth 2.0後,發送到服務器的cookie已更改爲加密的cookie。驗證並使用OAUTH 2.0從Facebook cookie獲取數據

我想,在服務器實現比老同一個Java示例代碼:

  • 我需要驗證調用,比如我使用cookie MD5伎倆知道以前那樣該呼叫已由我的客戶頁面完成。
  • 從該cookie獲取數據:我需要facebook用戶。

如果可能不調用FB,只使用cookie數據。

在此先感謝。

回答

8

好吧,雖然我有幾個很好的答案,我回答自己什麼我已經寫在我的博客: http://pablocastilla.wordpress.com/2011/09/25/how-to-implement-oauth-f/

現在的餅乾已經改變了很多:它是加密的,不具有的accessToken和其內容格式已經改變了很多。在這裏,你有幾個環節說起吧:

http://developers.facebook.com/docs/authentication/signed_request/

http://developers.facebook.com/docs/authentication/

http://blog.sociablelabs.com/2011/09/19/server-side-changes-facebook-oauth-2-0-upgrade/

所以驗證cookie的,從它那裏得到用戶並獲得訪問令牌,你可以使用此代碼:

public class FaceBookSecurity { 

// return the fb user in the cookie. 
public static String getFBUserFromCookie(HttpServletRequest request) 
     throws Exception { 
    Cookie fbCookie = getFBCookie(request); 

    if (fbCookie == null) 
     return null; 

    // gets cookie value 
    String fbCookieValue = fbCookie.getValue(); 

    // splits it. 
    String[] stringArgs = fbCookieValue.split("\\."); 
    String encodedPayload = stringArgs[1]; 

    String payload = base64UrlDecode(encodedPayload); 

    // gets the js object from the cookie 
    JsonObject data = new JsonObject(payload); 

    return data.getString("user_id"); 

} 

public static boolean ValidateFBCookie(HttpServletRequest request) 
     throws Exception { 

    Cookie fbCookie = getFBCookie(request); 

    if (fbCookie == null) 
     throw new NotLoggedInFacebookException(); 

    // gets cookie information 
    String fbCookieValue = fbCookie.getValue(); 

    String[] stringArgs = fbCookieValue.split("\\."); 
    String encodedSignature = stringArgs[0]; 
    String encodedPayload = stringArgs[1]; 

    //decode 
    String sig = base64UrlDecode(encodedSignature); 
    String payload = base64UrlDecode(encodedPayload); 

    // gets the js object from the cookie 
    JsonObject data = new JsonObject(payload); 

    if (!data.getString("algorithm").Equals("HMAC-SHA256")) { 
     return false; 
    } 

    SecretKey key = new SecretKeySpec(
      ApplicationServerConstants.FacebookSecretKey.getBytes(), 
      "hmacSHA256"); 

    Mac hmacSha256 = Mac.getInstance("hmacSHA256"); 
    hmacSha256.init(key); 
    // decode the info. 
    byte[] mac = hmacSha256.doFinal(encodedPayload.getBytes()); 

    String expectedSig = new String(mac); 

    // compare if the spected sig is the same than in the cookie. 
    return expectedSig.equals(sig); 

} 

public static String getFBAccessToken(HttpServletRequest request) 
     throws Exception { 
    Cookie fbCookie = getFBCookie(request); 

    String fbCookieValue = fbCookie.getValue(); 

    String[] stringArgs = fbCookieValue.split("\\."); 
    String encodedPayload = stringArgs[1]; 

    String payload = base64UrlDecode(encodedPayload); 

    // gets the js object from the cookie 
    JsonObject data = new JsonObject(payload); 

    String authUrl = getAuthURL(data.getString("code")); 
    URL url = new URL(authUrl); 
    URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), 
      url.getQuery(), null); 
    String result = readURL(uri.toURL()); 

    String[] resultSplited = result.split("&"); 

    return resultSplited[0].split("=")[1]; 

} 

// creates the url for calling to oauth. 
public static String getAuthURL(String authCode) { 
    String url = "https://graph.facebook.com/oauth/access_token?client_id=" 
      + ApplicationConstants.FacebookApiKey 
      + "&redirect_uri=&client_secret=" 
      + ApplicationServerConstants.FacebookSecretKey + "&code=" 
      + authCode; 

    return url; 
} 

// reads the url. 
private static String readURL(URL url) throws IOException { 

    InputStream is = url.openStream(); 

    InputStreamReader inStreamReader = new InputStreamReader(is); 
    BufferedReader reader = new BufferedReader(inStreamReader); 

    String s = ""; 

    int r; 
    while ((r = is.read()) != -1) { 
     s = reader.readLine(); 
    } 

    reader.close(); 
    return s; 
} 

private static String base64UrlDecode(String input) { 
    String result = null; 
    Base64 decoder = new Base64(true); 
    byte[] decodedBytes = decoder.decode(input); 
    result = new String(decodedBytes); 
    return result; 
} 

    private static Cookie getFBCookie(HttpServletRequest request) 
    { 
     Cookie[] cookies = request.getCookies(); 

     if (cookies == null) 
      return null; 

     Cookie fbCookie = null; 

     for (Cookie c : cookies) { 
      if (c.getName().equals(
       "fbsr_" + ApplicationServerConstants.FacebookApiKey)) { 
       fbCookie = c; 
      } 
     } 
     return fbCookie; 
    } 
} 
+2

if(data.getString(「algorithm」)!= 「HMAC-SHA256」){ 正確的是: 如果(! 「HMAC-SHA256」 .equals(data.getString( 「算法」))){ – uwe

1

我認爲cookie數據是任意格式的 - 因爲你不應該自己解釋它? SDK肯定會爲你驗證cookie嗎?

+0

但我需要在服務器中做到這一點。沒有sdk的java :(。 –

2

我只是說這BatchFB的新版本(2.1.1):http://code.google.com/p/batchfb/

獲得用戶ID:

FacebookCookie data = FacebookCookie.decode(cookie, YOURAPPSECRET); 
System.out.println("Facebook user id is " + data.getFbId()); 

你可以看到這裏的代碼,它使用傑克遜解析在JSON和javax.crypto.Mac中來驗證簽名:

http://code.google.com/p/batchfb/source/browse/trunk/src/com/googlecode/batchfb/FacebookCookie.java

不幸的是獲得訪問令牌是相當多的複雜。 fbsr_ cookie中包含的數據包含一個「代碼」,然後您可以使用該代碼來獲取圖形api以獲取真正的訪問令牌......您必須將它存儲在某個cookie或會話中。這是令人難以置信的跛腳。

更好的解決方案是從javascript設置您自己的訪問令牌cookie。每次調用FB.getLoginStatus()時,都要設置(或刪除)您自己的cookie。你不必擔心簽名訪問令牌,因爲它是不可猜測的。