2011-01-17 31 views
11

Tôi đang làm việc với API Facebook và Ruby on Rails và tôi đang cố gắng phân tích cú pháp JSON quay lại. Vấn đề tôi đang gặp phải là Facebook base64URL mã hóa dữ liệu của họ. Không có giải mã base64URL tích hợp cho Ruby.base 64 URL giải mã bằng Ruby/Rails?

Để biết sự khác biệt giữa mã hóa base64 và base64URL được mã hóa, see wikipedia.

Làm cách nào để giải mã điều này bằng Ruby/Rails?

Sửa:

Bởi vì một số người gặp khó khăn trong việc đọc - URL base64 khác với base64

Trả lời

5

Googling cho "base64 cho URL ruby ​​"và chọn kết quả đầu tiên dẫn tôi đến the answer

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

Chi tiết về mật mã không phải là lưu ý quan trọng là nó có thể chứa bất kỳ giá trị byte nào.

Sau đó, bạn có thể trợ giúp cho base64UrlDecode(data).

gì đang xảy ra là nó mất encoded_token và thay thế tất cả các -_ nhân vật với +/, tương ứng. Sau đó, nó giải mã dữ liệu được mã hóa base64 bằng unpack('m') và trả về phần tử đầu tiên trong mảng được trả về: Dữ liệu được giải mã của bạn.

+0

yea, tôi thấy http://www.ruby-forum.com/topic/167232, nhưng đây không phải là kết quả đầu tiên của tôi. trang thứ hai cho tôi .. anyway. Tôi không hiểu những gì mà thực sự không ... Tôi cần phải đi theo cách khác – sethvargo

+0

Tôi nghĩ rằng bạn muốn giải mã dữ liệu mà Facebook đang gửi cho bạn ...?Trong ví dụ trên, 'encoded_token' là những gì Facebook đang gửi cho bạn và' cipher_token' là kết quả giải mã. – davemyron

+0

Bạn có thể gặp lỗi JSON không đúng định dạng với giải pháp này do cách xử lý vùng đệm. Xem http://qugstart.com/blog/ruby-and-rails/facebook-base64-url-decode-for-signed_request/ để biết giải pháp. – pschang

5

Đối base64URL mã hóa chuỗi s ...

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

lẽ ... những gì nó làm gì? Tôi khá giỏi ruby, nhưng bạn đã đánh bại tôi. – sethvargo

+0

Nó chuyển từ '+' sang '-' và'/'thành' _', sẽ tạo ra base64 đơn giản, và sau đó nó sử dụng trình giải nén base64 tích hợp, trả về, tôi nghĩ, một mảng một phần tử, vì vậy chúng tôi lấy kết quả chuỗi thực tế với '[0]'. Bạn có thể thay thế '[0]' bằng '.first' – DigitalRoss

+0

Có vẻ như bạn cũng có thể đi theo một cách khác và chuyển đổi chuỗi được mã hóa base64 thành base64URL bằng' s.tr ('-_', '+ /') ' – DigitalRoss

3

Đó là con đường tôi phân tích signed_request của ứng dụng facebook của tôi

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 

Phần cứu hộ chỉ thêm một '}', becouse facebook là đủ kỳ lạ để cho nó ra khỏi de băm mã hóa đôi khi (có thể họ cố định nó đã...).

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

Câu trả lời của Dmitry là chính xác. Nó chiếm phần đệm dấu '=' phải xảy ra trước khi giải mã chuỗi. Tôi tiếp tục nhận được JSON không đúng định dạng và cuối cùng đã phát hiện ra rằng đó là do phần đệm. Read more about base64_url_decode for Facebook signed_request.

Đây là phương pháp đơn giản tôi đã sử dụng:

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

Tôi tin rằng chỉ hợp pháp để đệm 1 hoặc 2, không phải bằng 3 hoặc 4. ví dụ: nếu str.lenght.modulo (4) bằng 0, thì không được pad. http://en.wikipedia.org/wiki/Base64 –

+0

Lưu ý: Việc đệm với bốn '=' có vẻ bị ngắt nếu bạn sử dụng strict_decode64 hoặc urlsafe_decode64, nhưng được dung thứ bằng decode64. –

Các vấn đề liên quan