2011-01-17 20 views
11

Estoy trabajando con Facebook API y Ruby on Rails y estoy tratando de analizar el JSON que vuelve. El problema que me encuentro es que Facebook base64URL codifica sus datos. No hay una decodificación base64URL incorporada para Ruby.base 64 URL decodificar con Ruby/Rails?

Para la diferencia entre un codificado en base64 y codificado en base64URL, see wikipedia.

¿Cómo decodizo esto usando Ruby/Rails?

Editar:

Debido a que algunas personas tienen dificultad para leer - URL base 64 es diferente de la base 64

Respuesta

5

Google para "base 64 de URL ruby ​​"y elegir el primer resultado me llevó a the answer

cipher_token = encoded_token.tr('-_','+/').unpack('m')[0] 

Los detalles de cipher_token no son importante, salvo que puede contener cualquier valores de bytes.

Podrías, por supuesto, hacer una ayuda a base64UrlDecode(data).

Lo que sucede es que toma la encoded_token y reemplaza a todas las - y _ caracteres con + y /, respectivamente. Luego, decodifica los datos codificados en base64 con unpack('m') y devuelve el primer elemento en la matriz devuelta: sus datos decodificados.

+0

Sí, vi este http://www.ruby-forum.com/topic/167232, pero no fue mi primer resultado. segunda página para mí ... de todos modos. No entiendo lo que realmente hace ... Tengo que ir a la OTRA manera – sethvargo

+0

Pensé que querías descifrar los datos que Facebook te está enviando ...?En el ejemplo anterior, 'codded_token' es lo que Facebook te está enviando y' cipher_token' es el resultado decodificado. – davemyron

+0

Puede obtener un error JSON malformado con esta solución debido a la forma en que se maneja el relleno. Consulte http://qugstart.com/blog/ruby-and-rails/facebook-base64-url-decode-for-signed_request/ para la solución. – pschang

5

Para base64URL codificado cuerdas s ...

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

tal vez ... ¿qué se hace? Soy bastante bueno en ruby, pero me tienes vencido. – sethvargo

+0

Transcribe '+ 'a' -' y '/' a '_', lo que debería dar como resultado base64, y luego usa el desempaquetador de base64 integrado, que devuelve, creo, una matriz de un elemento, por lo que agarra el resultado de la cuerda real con '[0]'. Podría reemplazar '[0]' con '.first' – DigitalRoss

+0

Parece que también puede ir hacia el otro lado y convertir una cadena codificada en base64 a base64URL con' s.tr ('-_', '+ /') ' – DigitalRoss

3

Esa es mi forma de analizar el signed_request de mi solicitud 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 rescate sólo añadir un '}', lástima pues facebook es bastante raro que dejarlo salir de de hash codificado veces (tal vez fijados ya es ...).

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

Dmitry's answer is correct. Representa el relleno del signo '=' que debe ocurrir antes de la decodificación de la cadena. Seguí formando JSON malformado y finalmente descubrí que era debido al relleno. Read more about base64_url_decode for Facebook signed_request.

Aquí está el método simplificado utilicé:

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

Creo que es legal rellenar por 1 o 2, no por 3 o 4. p. Ej. si str.lenght.modulo (4) es cero, entonces no rellenes. http://en.wikipedia.org/wiki/Base64 –

+0

Nota: Relleno con cuatro '=' parece romperse si usa strict_decode64 o urlsafe_decode64, pero es tolerado por decode64. –

Cuestiones relacionadas