2011-09-13 12 views
6

Sto tentando di analizzare Facebook firm_request all'interno del doPost di Java Servlet. E decodifico la richiesta firmata usando Base64 di commons-codec-1.3. Ecco il codice che ho usato per farlo all'interno di doPostParsing Facebook signed_request utilizzando Java restituisce malformato 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())); 

quando ho System.out il jsonString è malformato servlet. A volte manca il finale } di JSON a volte manca "} alla fine della stringa.

Come posso ottenere la risposta JSON corretta da Facebook?

risposta

7

facebook utilizza Base64 per URL e probabilmente stai tentando di decodificare il testo utilizzando l'algoritmo Base64 standard. tra le altre cose, la variante dell'URL non richiede il riempimento con "=".

  1. si potrebbe aggiungere i caratteri necessari nel codice (imbottitura, ecc)
  2. è possibile utilizzare commons-codec 1.5 (nuova Base64 (true)), dove hanno aggiunto il supporto per questa codifica.
+0

Vedere ulteriori dettagli su Apache Commons Codec qui http://commons.apache.org/proper/commons-codec/ –

1

Non l'ho mai fatto in Java, quindi non ho una risposta completa, ma il fatto che a volte si perdono uno e talvolta due caratteri dalla fine della stringa suggerisce che potrebbe essere un problema con il padding di Base64. Potresti voler esportare il valore del payload e vedere se termina con '=', quindi jsonString manca '}' e quando il payload termina con '==' allora jsonString manca '"}'. Se questo sembra essere il caso poi qualcosa va storto con l'interpretazione dei segni uguali alla fine del payload che dovrebbero rappresentare i bit vuoti

Modifica: su ulteriore riflessione credo che questo sia dovuto al fatto che Facebook utilizza la codifica URL Base64 (che non add = come pad chars invece del normale Base64, mentre la funzione di decodifica è normale Base64 con il trailing = char.

+0

Quando stampo la richiesta firmata non mostra alcun = o == alla fine del payload. Significa che sto ricevendo la richiesta firmata sbagliata. C'è qualche possibilità di sbagliare a causa dell'URL che ho dato durante le impostazioni dell'app Facebook. – amadamala

+0

Penso che la tua funzione Java si aspetti che l'input sia riempito con = chars, ma Facebook non li sta usando. Provare a passare direttamente il payload invece di payload.getBytes() nel caso in cui decodeBase64 si comporta in modo diverso con una stringa. Quindi prova a saltare le chiamate sostitutive nel caso in cui decodeBase64 è impostato per rilevare automaticamente la codifica basata sulla presenza di -_ o +/chars.Se tutto fallisce, dovrai trovare un altro metodo che comprenda la variante URL di Base64, o fondere l'input o l'output per aggirare la mancata corrispondenza (che dovrebbe essere fattibile poiché influenzerà solo gli ultimi 1-2 caratteri). –

+0

controlla http: // qugstart.com/blog/ruby-and-rails/facebook-base64-url-decode-per-signed_request/ – maximbr

1

Ho aggiornato a common-codec-1.5 usando un codice molto simile a questo e non sto vivendo questo Problema: hai confermato che il carico utile è veramente malformato utilizzando un de programmatore?

4

Facebook invia valori "non imbottiti" Base64 (l'URL "standard") e questo è problematico per i decodificatori Java che non se lo aspettano. Si può dire di avere il problema quando la codifica Base64 dati che si desidera decodificare ha una lunghezza che non è un multiplo di 4.

Ho usato questa funzione per fissare i valori:

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

questo ha fatto il trucco per me. Grazie! – Ben

+0

Anche io. Grazie mille. –