2011-01-17 2 views
11

Sto lavorando con l'API di Facebook e Ruby on Rails e sto cercando di analizzare il JSON che ritorna. Il problema che sto incontrando è che Facebook base64URL codifica i propri dati. Non esiste una decodifica base64URL integrata per Ruby.base 64 decodifica URL con Ruby/Rails?

Per la differenza tra una codifica base64 codificata in base64URL, see wikipedia.

Come si decodifica utilizzando Ruby/Rails?

Edit:

Perché alcune persone hanno difficoltà a leggere - URL base64 è diverso da Base64

risposta

5

Googling per "Base64 per URL rubino "e scegliendo il primo risultato mi portano a the answer

I dettagli del cipher_token non sono importante, salvo che può contenere qualsiasi valore di byte .

Si potrebbe quindi, naturalmente, fare un aiuto per base64UrlDecode(data).

Quello che sta succedendo è che ci vuole il encoded_token e sostituisce tutte le - e _ caratteri rispettivamente con + e /,. Quindi, decodifica i dati codificati in base64 con unpack('m') e restituisce il primo elemento nell'array restituito: i tuoi dati decodificati.

+0

sì, ho visto questo http://www.ruby-forum.com/topic/167232, ma non era il mio primo risultato. seconda pagina per me .. comunque. Non capisco cosa sia in realtà ... Devo andare in ALTRA maniera – sethvargo

+0

Ho pensato che volessi decodificare i dati che Facebook ti sta inviando ...?Nell'esempio sopra, 'encoded_token' è ciò che Facebook ti sta inviando e' cipher_token' è il risultato decodificato. – davemyron

+0

È possibile che si verifichi un errore JSON non valido con questa soluzione a causa del modo in cui viene gestito il riempimento. Vedi http://qugstart.com/blog/ruby-and-rails/facebook-base64-url-decode-for-signed_request/ per la soluzione. – pschang

5

Per base64URL-stringa codificata s ...

s.tr('+/', '-_').unpack('m')[0] 
+0

forse ... che cosa è fare? Sono abbastanza bravo con il rubino, ma mi hai battuto. – sethvargo

+0

Trasloca '+' a '-' e'/'a' _', che dovrebbe fornire plain base64, e quindi usa il built-in base64 unpacker, che restituisce, penso, un array di un elemento, quindi prendi il risultato effettivo della stringa con '[0]'. È possibile sostituire '[0]' con '.first' – DigitalRoss

+0

Sembra che si possa andare anche nell'altro modo e convertire una stringa codificata in base64 in base64URL con' s.tr ('-_', '+ /') ' – DigitalRoss

3

Questo è il mio modo di analizzare il signed_request della mia applicazione facebook

def decode_facebook_hash(signed_request) 
    signature, encoded_hash = signed_request.split('.') 
    begin 
    ActiveSupport::JSON.decode(Base64.decode64(encoded_hash)) 
    rescue ActiveSupport::JSON::ParseError 
    ActiveSupport::JSON.decode(Base64.decode64(encoded_hash) + "}") 
    end 
end 

La parte Rescue Aggiungi solo un '}', siccome facebook è abbastanza strano di lasciarlo fuori de hash codificato a volte (forse lo hanno risolto già ...).

2
def decode64_url(str) 
    # add '=' padding 
    str = case str.length % 4 
    when 2 then str + '==' 
    when 3 then str + '=' 
    else 
     str 
    end 

    Base64.decode64(str.tr('-_', '+/')) 
end 
12

La risposta di Dmitry è corretta. Rappresenta il riempimento del segno "=" che deve verificarsi prima della decodifica della stringa. Ho continuato a ottenere JSON malformato e alla fine ho scoperto che era dovuto al padding. Read more about base64_url_decode for Facebook signed_request.

Ecco il metodo semplificato che ho usato:

def base64_url_decode(str) 
    str += '=' * (4 - str.length.modulo(4)) 
    Base64.decode64(str.tr('-_','+/')) 
end 
+0

Credo che sia legale pagare solo per 1 o 2, non per 3 o 4, ad es. se str.lenght.modulo (4) è zero, non eseguire il pad. http://en.wikipedia.org/wiki/Base64 –

+0

Nota: il riempimento con quattro '=' sembra interrompersi se si utilizza strict_decode64 o urlsafe_decode64, ma è tollerato dalla decodifica64. –