2013-07-05 44 views
25

Ho appena effettuato il passaggio da Rails 3.2 a Rails 4. Sto cercando di essere il più veloce possibile sui problemi di sicurezza e sono preoccupato per le sessioni in questo momento. Sembra che Rails 4 si sia allontanato dal supportare davvero qualsiasi ECCEZIONE di sessioni basate sui cookie, ma sembra che non sia possibile impedire che le sessioni basate su cookie vivano per sempre. Ho letto diversi articoli, ma questo è il più ufficiale: http://guides.rubyonrails.org/security.html#session-expiry. Si noti come fanno notare che questo è un problema per le sessioni basate sui cookie, quindi forniscono una correzione per le sessioni basate su database (che ora sono deprecate, apparentemente).Rails 4: Scadenza sessione?

Sono davvero confuso. Voglio essere in grado di impedire a un utente malintenzionato di ottenere un cookie che gli dia accesso permanente al mio sito protetto da accesso. Ovviamente posso impostare: expire_after in initializers/session_store.rb, ma a meno che non sbaglio, imposta semplicemente la scadenza del cookie che è lato client e facilmente alterata da un utente malintenzionato in modo che la sessione possa vivere per sempre. Ovviamente posso migliorare le cose forzando SSL, usando i cookie sicuri e costringendo solo HTTP, ma questa non sarà mai una difesa completa finché non riuscirò a far rispettare la scadenza della sessione.

Come posso risolvere questo problema quando Rails disapprova l'unico modo di avere sessioni lato server?

So che le sessioni di registrazione attive sono state spostate in una gemma ed è ancora disponibile, ma il fatto rimane che è stato deprecato. Una soluzione dovrebbe essere possibile senza introdurre più dipendenze o, quanto meno, senza utilizzare funzionalità deprecate.

+0

Perché questo sta ottenendo downvotes (senza commenti) diversi anni dopo che è stato chiesto? – Kyle

+0

È una domanda molto valida - e le guide di Rails sono ... beh .. cosa sono. Sarei lieto di sapere una buona risposta alla tua domanda perché capisco perfettamente perché ti sei confuso da ciò che è ancora lì, anche nell'ultimo "edge". – silverdr

risposta

34

Rails ha cookie di sessione "a prova di manomissione". Per evitare manomissioni di hash di sessione, un digest viene calcolato dalla sessione con un segreto sul lato server e inserito nella parte finale del cookie. Assicurati solo di avere un lungo segreto. Se vuoi resettare periodicamente tutte le sessioni utente cambia il tuo segreto.

Per rispondere alla tua domanda, se si desidera aggiungere un extra time-out per i dati di sessione che si possa fare:

session[:user_id] = user.id 
session[:expires_at] = Time.current + 24.hours 

Poi, quando l'autenticazione degli utenti, fare:

if session[:expires_at] < Time.current 
    # sign out user 
end 

Speranza questo aiuta

+4

Nota che questa soluzione non funzionerà di default con Rails 4.1 e successive. Il serializzatore dei cookie ora assume come valore predefinito JSON, quindi gli oggetti Time vengono memorizzati come stringhe. – Chewi

+3

'session [: expires_at] .to_time

+0

Probabilmente l'uso più comune è quello di scadere la sessione dopo un periodo di inattività preselezionato piuttosto che improvvisamente dal nulla perché il tempo di scadenza originale è passato. Ma questo non sembra (esplicitamente) che riguardi tale caso d'uso.Mettere la seconda linea come riga 'before_action' in Application Controller piuttosto che come parte dell'azione di login risolverebbe il problema. – silverdr

32

In realtà i binari ereditano da Rack::Session::Cookie. Quindi è possibile configurare il parametro expire_after nel proprio session_store.rb.

Sqore::Application.config.session_store(
    :cookie_store, 
    key: '_name_session', 
    expire_after: 24.hours 
) 
+1

Questa è la risposta migliore e dovrebbe essere scelta –

+4

No, il poster ha esplicitamente detto che non voleva farlo perché può essere manomesso dal lato client. – Chewi

+0

Ottima risposta. La documentazione è disponibile qui: http://api.rubyonrails.org/classes/ActionDispatch/Session/CookieStore.html – dontangg

1

aggiungere questo al controller dell'applicazione: before_filter: session_expires,: ad eccezione => [: login,: Esci] before_filter: update_session_time,: ad eccezione => [: login,: Esci]

def session_expires 
@time_left = (session[:expires_at] - Time.now).to_i 
unless @time_left > 0 
reset_session 
flash[:error] = 'Lorem Ipsum.' 
redirect_to :controller => 'foo', :action => 'bar' 
end 
end 

def update_session_time 
    session[:expires_at] = 60.minutes.from_now 
end