ActionController :: InvalidAuthenticityToken


148

Di seguito è riportato un errore, causato da un modulo nella mia applicazione Rails:

Processing UsersController#update (for **ip** at 2010-07-29 10:52:27) [PUT]
  Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"ysiDvO5s7qhJQrnlSR2+f8jF1gxdB7T9I2ydxpRlSSk=", **more parameters**}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

Questo accade per ogni non getrichiesta e, come vedi, authenticity_tokenc'è.

Risposte:


207

Ho avuto lo stesso problema ma con le pagine che erano nella cache della pagina. Le pagine sono state memorizzate con un token di autenticità non aggiornato e tutte le azioni che utilizzano i metodi post / put / delete sono state riconosciute come tentativi di falsificazione. Errore (422 entità non elaborabile) restituito all'utente.

La soluzione per Rails 3:
aggiungi:

 skip_before_filter :verify_authenticity_token  

o come "sagivo" sottolineato in Rails 4 aggiungere:

 skip_before_action :verify_authenticity_token

Nelle pagine che eseguono la memorizzazione nella cache.

Come ha commentato @toobulkeh, questa non è una vulnerabilità su :index, :showazioni, ma attenzione usando questa su :put, :postazioni.

Per esempio:

 caches_page :index, :show  
 skip_before_filter :verify_authenticity_token, :only => [:index, :show]

Riferimento: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html

Nota aggiunta da barlop- Rails 4.2 obsoleto skip_before_filter a favore di skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html "La famiglia di metodi * _filter è stata rimossa dalla documentazione. Il loro utilizzo è sconsigliato a favore dell'azione * _ famiglia di metodi "

Per Rails 6 (come sottolineato da "collimarco") è possibile utilizzare skip_forgery_protectione che è sicuro utilizzarlo per un'API REST che non utilizza i dati di sessione.


3
Probabilmente non è questo il caso, non sapevo di caches_page prima del tuo post. Ma controllerò caches_page , grazie.
Nikita Rybak,

7
in rotaie 4skip_before_action :verify_authenticity_token
Sagiv Ofek,

88
Non è questa una vulnerabilità?
quantumpotato,

6
non si tratta di una vulnerabilità in :index, :showazioni. Ma diffidare di mettere questo in :put, :postazione!
toobulkeh,

14
anche se sono d'accordo che a volte hai il caso in cui ciò è necessario (come forse una volta nella vita), ma devi capire che stai riparando la sicurezza disabilitando la sicurezza. Non raccomandato
equivalente8

77

Per me la causa di questo problema in Rails 4 era mancante,

<%= csrf_meta_tags %>

Linea nel layout principale dell'applicazione. L'ho cancellato per errore quando riscrivo il layout.

Se questo non è nel layout principale, sarà necessario in qualsiasi pagina su cui desideri un token CSRF.


2
Stiamo anche ricevendo questo errore. Ma è interrotto. Potrebbe essere questo il motivo o non avere questo effetto su ogni richiesta con un errore?
Ryan-Neal Mes

@ Ryan-NealMes, se nel tuo modello manca quella linea, otterrai l'errore. Quindi è possibile che alcuni dei tuoi modelli lo abbiano e altri no.
James McMahon,

1
@JamesMcMahon grazie, ho capito che il mio caso è in realtà causato dalla cancellazione dei cookie da parte degli utenti o dal blocco dei cookie. Carichi appresi da questa domanda!
Ryan-Neal Mes

61

Esistono diverse cause per questo errore (relative a Rails 4).

1. Verifica <%= csrf_meta_tags %>presente nel layout di pagina

2. controlla che il token di autenticità venga inviato con le chiamate AJAX se usi l' form_forhelper con l' remote: trueopzione. In caso contrario puoi includere la linea all'interno <%= hidden_field_tag :authenticity_token, form_authenticity_token %>del blocco del modulo.

3. Se la richiesta viene inviata dalla pagina memorizzata nella cache, utilizzare la memorizzazione nella cache dei frammenti per escludere una parte della pagina che invia la richiesta, ad es button_to. Ecc. Altrimenti il ​​token sarà stantio / non valido.

Sarei riluttante a annullare la protezione CSRF ...


csrf_meta_tags dovrebbe essere in <head>? Come posso essere sicuro che non sia in conflitto con i turbolink?
scintilla il

37

L'aggiunta del authenticity_tokenmodulo è stata risolta per me.

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

3
Rails dovrebbe inviare il token per impostazione predefinita. Non vogliamo specificarlo esplicitamente. Sento che il token è cambiato in qualche modo in questa situazione qui.
Abhi,

1
Tuttavia, se hai creato il modulo senza utilizzare gli helper, dovresti inserirlo manualmente.
André Guimarães Sakata,

30

Il token di autenticità è un valore casuale generato nella tua vista per dimostrare che una richiesta viene inviata da un modulo sul tuo sito, non altrove. Questo protegge dagli attacchi CSRF:

http://en.wikipedia.org/wiki/Cross-site_request_forgery

Controlla per vedere chi è quel client / IP, sembra che stiano usando il tuo sito senza caricare le tue visualizzazioni.

Se è necessario eseguire il debug ulteriormente, questa domanda è un buon punto di partenza: comprendere il token di autenticità di Rails

Modificato per spiegare: significa che stanno chiamando l'azione per elaborare il modulo inoltrato senza mai renderlo sul tuo sito web. Questo potrebbe essere dannoso (ad esempio postare commenti spam) o potrebbe indicare un cliente che tenta di utilizzare direttamente l'API del servizio Web. Sei l'unico che può rispondere a ciò per la natura del tuo prodotto e analizzare le tue richieste.


1
Grazie, ma so già cos'è il token di autenticità. Controlla per vedere chi è quel client / IP, sembra che stiano usando il tuo sito senza caricare le tue visualizzazioni. Spiacenti, cosa significa "senza caricare le visualizzazioni"?
Nikita Rybak,

1
Voglio dire che qualcuno (probabilmente uno spammer) potrebbe inviare dati al modulo senza passare attraverso l'interfaccia utente dell'applicazione. È possibile farlo utilizzando un programma da riga di comando come ad esempio curl.
John Topley,

John ha esattamente ragione. Significa che stanno chiamando l'azione per elaborare il modulo inoltrato senza mai renderlo sul tuo sito web. Ciò potrebbe essere dannoso (ad esempio postare commenti spam) o indicare un cliente che sta tentando di utilizzare direttamente l'API del servizio Web. Sei l'unico che può rispondere a ciò per la natura del tuo prodotto e analizzare le tue richieste.
Winfield,

Ok, ho frainteso il commento di Winfield. Pensavo che l'app non fosse in qualche modo configurata per "caricare le mie visualizzazioni" quando utilizzo il browser.
Nikita Rybak,

1
Ho anche avuto un altro pensiero, queste richieste includono un token, ma non è valido. Ciò potrebbe essere causato dalla memorizzazione nella cache della pagina che rende il modulo o qualcos'altro che causa potenzialmente una versione obsoleta del modulo.
Winfield,

27

ActionController::InvalidAuthenticityTokenpuò anche essere causato da un proxy inverso non configurato correttamente. Questo è il caso se nella traccia dello stack si ottiene una linea simile Request origin does not match request base_url.

Quando si utilizza un proxy inverso (come nginx) come ricevitore per la richiesta HTTPS e si trasmette la richiesta non crittografata al back-end (come l'app Rails), il back-end (in particolare: Rack) prevede alcune intestazioni con ulteriori informazioni sulla richiesta client originale al fine di poter applicare varie attività di elaborazione e misure di sicurezza.

Maggiori dettagli sono disponibili qui: https://github.com/rails/rails/issues/22965 .

TL; DR: la soluzione è aggiungere alcune intestazioni:

upstream myapp {
  server              unix:///path/to/puma.sock;
}

location / {
  proxy_pass        http://myapp;
  proxy_set_header  Host $host;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header  X-Forwarded-Proto $scheme;
  proxy_set_header  X-Forwarded-Ssl on; # Optional
  proxy_set_header  X-Forwarded-Port $server_port;
  proxy_set_header  X-Forwarded-Host $host;
}

Caspita, sto cercando da 3 ore una soluzione per questo, ed è stato così, grazie!
evexoio,

grazie mille 6 ore per aver cercato di risolverlo dal lato delle rotaie
Joe Half Face,

18

troppo tardi per rispondere ma ho trovato la soluzione.

Quando si definisce il proprio modulo HTML, si perde la stringa del token di autenticazione che deve essere inviata al controller per motivi di sicurezza. Ma quando si utilizza l'helper del modulo rotaie per generare un modulo, si ottiene qualcosa di simile al seguente

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;">
    <input name="authenticity_token" type="hidden" 
      value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
    .
    .
    .
  </div>
</form>

Quindi la soluzione al problema è quella di aggiungere il campo authenticity_token o utilizzare gli helper dei binari piuttosto che rimuovere, declassare o aggiornare i binari.


9

Se hai rake rails:updatemodificato o modificato di recente il tuo config/initializers/session_store.rb, questo potrebbe essere un sintomo di vecchi cookie nel browser. Spero che questo avvenga in dev / test (è stato per me) e puoi semplicemente cancellare tutti i cookie del browser relativi al dominio in questione.

Se questo è in produzione e hai cambiato key, considera di cambiarlo per usare i vecchi cookie (<- solo speculazioni).


Sì! Per me, avere un session_store.rb vuoto stava causando l'errore.
Lafeber

6

Ho avuto questo problema con le chiamate javascript. L'ho risolto richiedendo solo jquery_ujs nel file application.js.


Sì, ho riscontrato questo problema e ho aggiunto jquery_ujs nell'applicazione js. Ha funzionato.
Abhi,

3

Abbiamo avuto lo stesso problema, ma abbiamo notato che era solo per richieste che utilizzavano http: // e non con https: //. La causa era secure: trueper session_store:

Rails.application.config.session_store(
  :cookie_store,
  key: '_foo_session',
  domain: '.example.com',
  secure: true
)

Risolto usando HTTPS ~ ovunque :)


L'ho riscontrato quando si utilizzava rails s(non SSL) invece dell'endpoint SSL che ho impostato per lo sviluppo. Solo quando ho letto il tuo commento ho capito cosa stavo facendo. Una volta tornato a utilizzare SSL, le cose hanno ripreso a funzionare. Grazie!
Karl Wilbur,

1
Ho affrontato questo problema in fase di sviluppo. Invece di secure: trueaver scrittosecure: !Rails.env.development?
murb il

1

Per le rotaie 5, è meglio aggiungere protect_from_forgery prepend: trueche saltare ilverify_authentication_token


5
Perché? Potresti aggiungere un riferimento?
kwerle


0

Ho avuto questo problema e il motivo è stato perché ho copiato e incollato un controller nella mia app. Ho dovuto cambiare ApplicationControllerinApplicationController::Base


0

Ho avuto lo stesso problema su localhost. Ho cambiato il dominio per l'app, ma negli URL e nei file host c'era ancora il vecchio dominio. Aggiornato i segnalibri del mio browser e il file host per utilizzare il nuovo dominio e ora tutto funziona correttamente.


0

Forse hai la tua configurazione NGINX per HTTPS ma i tuoi certificati non sono validi? Ho avuto un problema simile in passato e il reindirizzamento da http a https ha risolto il problema


0

Ho verificato che <% = csrf_meta_tags%> sono presenti e che la cancellazione dei cookie nel browser ha funzionato per me.


0

Seguendo i consigli di Chrome Lighthouse per un caricamento più rapido dell'applicazione, ho sincronizzato il mio Javascript:

views/layout/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload', async: true %>

Questo ha rotto tutto e ha ottenuto quell'errore Token per i miei moduli remoti. La rimozione ha async: truerisolto il problema.


0

Questa risposta è molto più specifica di Ruby on Rails, ma speriamo che possa aiutare qualcuno.

Devi includere il token CSRF in ogni richiesta non GET. Se sei abituato a usare JQuery, Rails ha una libreria di supporto chiamata jquery-ujsche si basa su di essa e aggiunge alcune funzionalità nascoste. Una delle cose che fa è includere automaticamente il token CSRF in ogni ajaxrichiesta. Vedere qui .

Se passi da esso come ho fatto potresti ritrovarti con un errore. È possibile semplicemente inviare il token manualmente o utilizzare un'altra libreria per eliminare il token dal DOM. Vedi questo post per maggiori dettagli.


0

Per l'ambiente di sviluppo, ho provato molti di questi tentativi di risolvere questo problema in Rails 6. Nessuno di questi ha aiutato. Quindi, se nessuno di questi suggerimenti ha funzionato per te, prova di seguito.

L'unica soluzione che ho trovato è stata quella di aggiungere un file txt nella cartella / tmp.

Nella directory principale della tua app, esegui:

touch tmp/caching-dev.txt

Oppure crea manualmente un file con quel nome nella cartella / tmp. Dal momento che ciò ha risolto il problema per me, presumo che la radice del problema sia un conflitto di cache.


-1

In rails 5, dobbiamo aggiungere 2 righe di codice

    skip_before_action :verify_authenticity_token
    protect_from_forgery prepend: true, with: :exception

-2

Installazione

gem 'remotipart' 

può aiutare


3
anche se questa potrebbe essere la risposta, ma è anche utile includere la parte essenziale della risposta e spiegare perché / come funziona.
Roy Lee,

-15

Problema risolto declassando da 2.3.8 a 2.3.5. (oltre al famigerato problema "Stai per essere reindirizzato.")


@Flip forse è un'idea per aggiornare la risposta accettata?
Lafeber
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.