2009-12-21 14 views
19

Ho una domanda su come Rails gestisce la crittografia/decrittografia dei cookie .Data la chiave di sessione e il segreto, come possiamo decifrare i cookie di Rails?

ho questo nel mio config/environment.rb

config.action_controller.session = { 
    :session_key => [some key], 
    :secret => [some secret] 
    } 

E questo in config/ambiente/production.rb et al .:

ActionController::Base.session_options[:session_domain] = [some 
domain] 

Fin qui, tutto bene - - Finché tutte le mie app Rails hanno la stessa chiave di sessione e sono sullo stesso dominio, possono utilizzare lo stesso cookie .

Tuttavia, un collega ha ora un'applicazione JSP (nello stesso dominio), con cui vorrebbe leggere i cookie che ho impostato.

Quindi, dato un valore di cookie segreto e crittografato, come dovremmo decodificare per ottenere il contenuto di tale cookie?

(La documentazione sembrano indicare questo è a senso unico la crittografia SHA1 per default - http://caboo.se/doc/classes/CGI/Session/CookieStore.html - ma poi come le mie applicazioni Rails avrebbero leggere il contenuto di un cookie che è a senso unico criptato?)

Grazie in anticipo per eventuali suggerimenti/puntatori/intuizione,

Joe

+0

http://www.railshorde.com/blog/rails-decode-session-cookie – Animesh

risposta

12

Rails usa HMAC-SHA1 per la crittografia dei dati dei cookie, che è diverso da un sistema di crittografia SHA1 a senso unico, come si sospetta (vedi the Wikipedia article on HMAC per una e Xplanation). La crittografia viene eseguita dalla classe ActiveSupport::MessageVerifier (il codice sorgente è abbastanza leggibile). Ecco un esempio basato su un'applicazione Rails di prova:

secret = 'b6ff5a9c3c97bf89afe9a72e6667bafe855390e8570d46e16e9760f6394' + 
    '4ab05577b211ec2f43f6c970441518f0241775499bde055078f754c33b62f68ba27ca' 

cookie = "_test_session=BAh7CCIYdXNlcl9jcmVkZW50aWFsc19pZGkGIhV1c2VyX2NyZW" + 
    "RlbnRpYWxzIgGAMzBlODkxZDQ2MWZhNjFkMDFmNzczMmJjNDdjMjIwZGFjMTY2NWEwNDMwZ" + 
    "DVjMmUxOWY5MDFjMjQ5NWQ4OTM1OGZlMzE3NzRiZTFiZjM1ZTVlZDY2ZGUzYTkwOWZjZTgw" + 
    "NTFlNGUxZWI0MTUzYTRjODZiMGZmMzM3NzliM2U3YzI6D3Nlc3Npb25faWQiJTgxNzk0Yjd" + 
    "kN2IxYzRjMDE0M2QwOTk5NTVjZjUwZTVm--25c8f3222ab1be9f2394e2795a9f2557b06d0a92" 

session = cookie.split('=').last 
verifier = ActiveSupport::MessageVerifier.new(secret, 'SHA1') 
verifier.verify(session) 

Questo dovrebbe restituire l'hash della sessione che ci si aspetta. Per implementarlo in Java, il tuo collega dovrà duplicare il metodo ActiveSupport::MessageVerifier#verify. Il codice sorgente è nella directory gems (/usr/lib/ruby/gems/1.8/gems sul mio sistema) al numero activesupport-2.3.5/lib/active_support/message_verifier.rb.

+6

Penso che la tua risposta non sia giusta. HMAC-SHA1 è un algoritmo che viene utilizzato per verificare l'autenticità di una stringa di dati. Funziona calcolando un digest del messaggio utilizzando una funzione di hash unidirezionale e con un digest generato quando il messaggio è stato creato. Non c'è nessuna crittografia in corso. – heathd

17

Se si tira il campo session.data direttamente dai dati di sessione memorizzati nel database del vostro app (se si utilizza active_record_store nel file environment.rb)

config.action_controller.session_store = :active_record_store 

... ecco come si decodifica e restituire il hash:

Marshal.load(ActiveSupport::Base64.decode64(@session.data)) 

... o in Rails> = 3.2 (grazie Chuck Vose)

Marshal.load(Base64.decode64(@session.data)) 

Non è affatto crittografato.

+0

Purtroppo, sto usando i cookie per le sessioni su questo particolare progetto. Non vedo nulla di specifico del database nella tua linea per decodificarlo. "Decifrare" è la parola sbagliata; Avrei dovuto dire "decodificare". Grazie per il suggerimento. –

+1

In Rails3.2 ActiveSupport non è più il genitore di Base64. Basta eliminare ActiveSupport :: per farlo funzionare. Vale anche la pena notare che, se si esegue il debug, è possibile interrompere Marshal.load se ti dà problemi. –

7

Per impostazione predefinita, Rails (prima della versione 4) non crittografa i cookie di sessione, li firma solo. Per crittografare loro, è necessario fare qualcosa di simile a questa:

ActionController::Base.session_store = EncryptedCookieStore 

Ci sono diversi plugin che forniscono questo tipo di funzionalità di crittografia.

Quindi, se non si utilizza specificamente un archivio crittografato, tutto il codice Java deve fare è verificare la firma del cookie e decodificare il cookie. Come dice Alex nella sua risposta, è necessario duplicare la funzionalità di ActiveSupport::MessageVerifier#verify e condividere la chiave con l'applicazione Java. Che entrambi verificano e decodifica il cookie.

Se non si desidera verificare la firma (che NON è consigliabile), è possibile utilizzare il metodo di decodifica Midwire da Base64 per visualizzare l'hash della sessione. In Ruby, questo è:

Marshal.load(ActiveSupport::Base64.decode64(the_cookie_value)) 

So che questo è vecchio, ma spero che questo aiuti qualcuno!

(Aggiornamento: La domanda si riferisce a Rails 3. A partire da Rails 4, i cookie di sessione vengono crittografati per impostazione predefinita.)

9

Ecco come decifrare il cookie di sessione in Rails 4

def decrypt_session_cookie(cookie) 
    cookie = CGI.unescape(cookie) 
    config = Rails.application.config 

    encrypted_cookie_salt = config.action_dispatch.encrypted_cookie_salt    # "encrypted cookie" by default 
    encrypted_signed_cookie_salt = config.action_dispatch.encrypted_signed_cookie_salt # "signed encrypted cookie" by default 

    key_generator = ActiveSupport::KeyGenerator.new(config.secret_key_base, iterations: 1000) 
    secret = key_generator.generate_key(encrypted_cookie_salt) 
    sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt) 

    encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret) 
    encryptor.decrypt_and_verify(cookie) 
end 

http://big-elephants.com/2014-01/handling-rails-4-sessions-with-go/

+0

Ho dovuto usare 'Rails.application.secrets.secret_key_base' invece di' config.secret_key_base' (quest'ultimo era nullo nell'ambiente di sviluppo) durante la creazione di ActiveSupport :: KeyGenerator per farlo funzionare. –

1

Ho scritto una gemma Ruby per gestire i cookie gestiti dalle app Rails. Leggendo la sua sorgente si può capire come funziona e possibilmente porta a Java in modo che il JSP applicazione potrebbe utilizzare tale:

https://github.com/rosenfeld/rails_compatible_cookies_utils

E 'un singolo file con ~ 150 linee di codice che gestisce anche firmato solo valori dei cookie e si occupa di firmare/crittografare e verificare/decifrare, mentre sembra che tu sia preoccupato solo della decrittografia. Questo è il metodo per decifrare:

https://github.com/rosenfeld/rails_compatible_cookies_utils/blob/master/lib/rails_compatible_cookies_utils.rb#L41-L52

esso valori ricordare che oltre la chiave e il segreto avrete anche bisogno di sapere che serializzatore viene utilizzato. Un tempo era Maresciallo, ma sembra che l'impostazione predefinita per le app di nuova generazione sia ora JSON. Se è stato utilizzato Marshal, potrebbe essere difficile convertire tale codice in Java, in quanto dovresti trovare una libreria che implementa il carico di # Marshal di Ruby.

+1

Questo è stato molto utile, grazie. Il controllo della fonte è stato molto più semplice poiché è più compatto rispetto ad altre soluzioni e mi ha aiutato a duplicare le funzionalità in Elixir. – dimitarvp

+1

Sì, è stata una mia idea. Pensavo che le persone disposte a implementare la stessa logica in altre lingue trarrebbero vantaggio dall'ottenere la logica tutta concentrata in un singolo punto. Sono contento che ti abbia aiutato :) – rosenfeld

Problemi correlati