2011-09-13 85 views
6

我想解析Java Servlet的doPost中的Facebook signed_request。我使用commons-codec-1.3的Base64解碼已簽名的請求。 這裏是我以前做的代碼,這裏面的servlet的doPost使用Java解析Facebook signed_request返回格式不正確的JSON

String signedRequest = (String) req.getParameter("signed_request"); 
String payload = signedRequest.split("[.]", 2)[1]; 
payload = payload.replace("-", "+").replace("_", "/").trim(); 
String jsonString = new String(Base64.decodeBase64(payload.getBytes())); 

,當我的System.out的jsonString它的格式不正確。有時它會錯過JSON 的結尾},有時它會錯過字符串末尾的"}

如何從Facebook獲得正確的JSON響應?

回答

7

臉書正在使用Base64的URL,你可能試圖使用標準的Base64算法解碼文本。 除此之外,URL變體不需要填充「=」。

  1. 你可以在代碼(填充等)添加所需的字符
  2. 你可以使用commons-編解碼器1.5(新的Base64(真)),在那裏他們增加了對這種編碼的支持。
+0

查看更多關於Apache Commons Codec的詳細信息http://commons.apache.org/proper/commons-codec/ –

1

我從來沒有在Java中這樣做過,因此我沒有完整的答案,但事實上,有時從字符串末尾丟失一個,有時甚至是兩個字符,這表明它可能是Base64填充的問題。您可能想要輸出有效負載的值,並查看它何時以'='結尾,然後jsonString缺少'}',並且當有效負載以'=='結尾時,則jsonString丟失'「}'。如果這似乎是那麼在解釋有效載荷末尾的等號(它應該表示空位)時出現了一些問題。

編輯:在進一步的反思中,我認爲這是因爲Facebook使用的是Base64 URL編碼(它沒有add = as pad chars)而不是普通的Base64,而你的解碼函數期望普通的Base64跟蹤=字符。

+0

當我打印signed_request它沒有在有效載荷的末尾顯示任何=或==。這是否意味着我收到了錯誤的簽名請求。有沒有可能因爲我在Facebook應用程序設置期間提供的網址而導致它錯誤。 – amadamala

+0

我認爲你的Java函數期望輸入被填充=字符,但Facebook沒有使用它們。如果decodeBase64的行爲與字符串的行爲不同,請嘗試直接傳遞有效內容而不是payload.getBytes()。然後嘗試跳過替換調用,以防decodeBase64設置爲基於-_或+/chars自動檢測編碼。如果全部失敗,則必須找到另一種方法來了解Base64的URL變體,或fudge要麼輸入或輸出解決失配(這應該是可行的,因爲它只會影響最後1-2個字符)。 –

+0

查看http:// qugstart。com/blog/ruby​​-and-rails/facebook-base64-url-decode-for-signed_request/ – maximbr

1

我已經升級到common-codec-1.5,使用的代碼非常類似於這個,我沒有遇到過問題:您是否確認使用在線de確實負載確實不正確編碼器?

4

Facebook正在向您發送「unpadded」Base64值(URL「標準」),這對於不期望它的Java解碼器來說是有問題的。你可以告訴你,當Base64編碼要解碼數據的長度不是4

多我用這個功能來修復價值的問題:

public static String padBase64(String b64) { 
    String padding = ""; 
    // If you are a java developer, *this* is the critical bit.. FB expects 
    // the base64 decode to do this padding for you (as the PHP one 
    // apparently 
    // does... 
    switch (b64.length() % 4) { 
    case 0: 
     break; 
    case 1: 
     padding = "==="; 
     break; 
    case 2: 
     padding = "=="; 
     break; 
    default: 
     padding = "="; 
    } 
    return b64 + padding; 

} 
+0

this did我的詭計。謝謝! – Ben

+0

我也是。非常感謝你。 –