Ecco alcuni estratti di come ho ottenuto il mio CSRF lavorare per tutti i diversi scenari nella mia richiesta jQuery mobile che ho recentemente aggiornato a utilizzare laravel 5:
ho aggiunto un token CSRF cifrato in una variabile che verrà passato ai miei punti di vista nel mio controller principale base: app\Http\Controllers\MyController.php
$this->data['encrypted_csrf_token'] = Crypt::encrypt(csrf_token());
Poi, ho aggiunto il meta tag a mio avviso principale intestazione: resources\views\partials\htmlHeader.blade.php
<meta name="_token" content="{!! $encrypted_csrf_token !!}"/>
Poi, ho anche aggiunto questo jquery frammento come suggerito in alcuni forum:
$(function() {
$.ajaxSetup({
headers: {
'X-XSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
});
Ma, la chiave (almeno per il mio setup) era l'aggiunta del controllo per il cookie XSRF-TOKEN
nel mio middleware VerifyCsrfToken personalizzato: app\Http\Middleware\VerifyCsrfToken.php:
/**
* Determine if the session and input CSRF tokens match.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function tokensMatch($request)
{
$token = $request->session()->token();
$header = $request->header('X-XSRF-TOKEN');
$cookie = $request->cookie('XSRF-TOKEN');
return StringUtils::equals($token, $request->input('_token')) ||
($header && StringUtils::equals($token, $this->encrypter->decrypt($header))) ||
($cookie && StringUtils::equals($token, $cookie));
}
Prima ho aggiunto che, quasi tutti i miei post AJAX (tra cui l'invio di moduli ea elenco lazyloading) sono insufficienti a causa di una TokenMismatchException
.
EDIT: Il secondo pensiero, io non sono sicuro di quanto senso abbia per confrontare il token di sessione rispetto a quella impostata nel cookie (che sarebbe venuto dal token di sessione, in primo luogo giusto?). Questo potrebbe aver semplicemente scavalcato la sicurezza di tutto questo.
Penso che il mio problema principale fosse con il frammento jquery al di sopra del quale si supponeva fosse l'aggiunta dell'intestazione X-XSRF-TOKEN ad ogni richiesta Ajax. Questo non funzionava per me nella mia app in jQuery Mobile (nello specifico, nel mio lazyloader plugin) finché non ho aggiunto alcune opzioni per il plugin stesso. Ho aggiunto un nuovo selettore predefinito csrf
(che in questo caso sarebbe meta[name="_token"]
) e una nuova impostazione predefinita csrfHeaderKey
(che in questo caso sarebbe X-XSRF-TOKEN
). Fondamentalmente, durante l'inizializzazione del plug-in, una nuova proprietà _headers
viene inizializzata con il token CSRF se ne è disponibile uno dal selettore csrf
(predefinito o definito dall'utente). Quindi, nei 3 diversi posti in cui un POST ajax può essere sparato (quando si ripristinano le variabili di sessione o quando si esegue il mirroring di una listview) l'opzione di intestazioni di $ .ajax viene impostata con qualsiasi cosa sia in _headers
.
In ogni caso, poiché il X-XSRF-TOKEN ricevuto sul lato server proviene dal meta _token crittografato, penso che la protezione CSRF funzioni ora come dovrebbe.
mio app\Http\Middleware\VerifyCsrfToken.php
ora assomiglia a questo (che è essenzialmente di nuovo alla implementazione di default fornito da laravel 5 - LOL):
/**
* Determine if the session and input CSRF tokens match.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function tokensMatch($request)
{
$token = $request->session()->token();
$_token = $request->input('_token');
$header = $request->header('X-XSRF-TOKEN');
return StringUtils::equals($token, $_token) ||
($header && StringUtils::equals($token, $this->encrypter->decrypt($header)));
}
Nizza, in L5 sarebbe {!! Form :: token() !!} – raphadko
@RaphaelCabrera Sì hai ragione. Accidenti, non mi abituerò mai a '{!!' ... Fortunatamente puoi cambiarli :) – lukasgeiter
Non riesci a inviare di nuovo il modulo con lo stesso token dopo l'errore di validazione – mvladk