base 64 URL decode with Ruby/Rails?
I am working with the Facebook API and Ruby on Rails and I'm trying to parse the JSON that comes back. The problem I'm running into is that Facebook base64URL encodes their data. There is no built-in base64URL decode for Ruby.
For the difference between a base64 encoded and base64URL encoded, see wikipedia.
How do I decode 开发者_JAVA技巧this using Ruby/Rails?
Edit:
Because some people have difficulty reading - base64 URL is DIFFERENT than base64
Dmitry's answer is correct. It accounts for the '=' sign padding that must occur before string decode. I kept getting malformed JSON and finally discovered that it was due to the padding. Read more about base64_url_decode for Facebook signed_request.
Here's the simplified method I used:
def base64_url_decode(str)
str += '=' * (4 - str.length.modulo(4))
Base64.decode64(str.tr('-_','+/'))
end
Googling for "base64 for URL ruby" and choosing the first result lead me to the answer
cipher_token = encoded_token.tr('-_','+/').unpack('m')[0]
The details of the cipher_token aren't important save that it can contain any byte values.
You could then, of course, make a helper to base64UrlDecode( data )
.
What's happening is that it takes the encoded_token
and replaces all the -
and _
characters with +
and /
, respectively. Then, it decodes the base64-encoded data with unpack('m')
and returns the first element in the returned array: Your decoded data.
For base64URL-encoded string s
...
s.tr('+/', '-_').unpack('m')[0]
That's the way i parse the signed_request of my facebook application
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
The rescue part only add a '}', becouse facebook is weird enough to let it out of de encoded hash sometimes (maybe they fixed it already...).
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
精彩评论