Considerate questo punto di vista Django che otterrà un elenco di elementi associati all'utente corrente:Qual è il modo migliore per gestire i timeout delle sessioni nelle richieste Ajax?
@login_required
def list_items(request, page_number=0):
items = Paginator(request.user.items, 5).page(page_number).object_list
return HttpResponse(cjson.encode(items))
Ovviamente, vuole utilizzare il login_required
decoratore, per limitare l'accesso alla visualizzazione per gli utenti registrati.
Cosa fa quando un utente non autenticato tenta di accedere alla vista? Restituisce un HttpResponseRedirect
verso settings.LOGIN_URL
.
Considerate questo codice JavaScript, che chiama la vista:
var getPage = function(pageNumber) {
$.ajax({
url: "/list_items/" + pageNumber + "/",
success: function(data) {
$("#list_container").html(formatData(data))
}
});
};
Supponiamo settings.SESSION_COOKIE_AGE = 60
secondi.
Se un utente va a pagina 1, lo legge per 61 secondi, poi clicca sul pulsante per la pagina 2, login_required
decoratore di Django rileverà che la sessione non è più attivo, e restituirà un HttpResponseRedirect(settings.LOGIN_URL)
, che farà sì che il success
callback per ottenere una pagina di accesso HTML anziché l'elenco codificato JSON.
This is where it happens.
It's called by user_passes_test
here.
Qual è il modo migliore per gestire questa situazione?
Ecco un paio di cose che ho pensato di:
1.
Il success
callback deve controllare la risposta, e vedere se ottiene una pagina di accesso, con qualsiasi mezzo (controllare se il tipo di contenuto è html, controllare i contenuti , eccetera). Ma questo significa che dobbiamo avvolgere tutte le chiamate AJAX con un wrapper di richiamata in questo modo:
$.ajax({
url: "/list_items/" + pageNumber + "/",
success: sessionExpiryCallbackWrapper(function(data) {
$("#list_container").html(formatData(data))
})
});
Ma questo è brutto, e gli sviluppatori potrebbe dimenticare di fare questo in tutto il mondo.
2.
Utilizzare $.ajaxComplete
per gestire tutte le richieste.
$.ajaxComplete(globalCompleteCallback);
$.ajax({
success: successCallback,
complete: completeCallback
});
Ma questo è l'ordine di chiamata:
successCallback(); // success is called before complete
completeCallback();
globalCompleteCallback(); // this is called after the local callback
Così abbiamo solo prendere il reindirizzamento, dopo successCallback ha fallito, e possibilmente con JS errori a causa dei dati non validi ricevuti.
3.
Se login_required
sarebbero tornati 403 sulle richieste AJAX:
if not user.is_authenticated():
if request.is_ajax():
# send 403 to ajax calls
return HttpResponse403("you are not logged in")
else:
# regular code path
return HttpResponseRedirect(settings.LOGIN_URL)
Ma login_required
utilizza solo user_passes_test
che non fa questo.
user_passes_test
ha un sacco di funzionalità, quindi non è una buona idea reimplementarlo.
Qual è il modo migliore per gestire i timeout per le chiamate AJAX?
Scusate ma ho intenzione di diventare tutto filosofico su di voi. Lo scopo originale dei timeout delle sessioni era impedire al server di conservare risorse significative o dover eseguire operazioni costose per ogni richiesta. Ora abbiamo strutture client-side che eseguono la maggior parte del lavoro. Quindi perché sono necessari anche brevi timeout di sessione? –
@DaveMethvin I timeout della sessione sono necessari per restringere la finestra per il dirottamento della sessione sia a) sul filo/aria o b) fisicamente da qualcuno che accede al computer di qualcun altro dopo che è passato un po 'di AFK. – Prody
Questo problema sembra abbastanza facile da risolvere, basta avere i timeout della sessione del client più brevi di quelli del server. In questo caso, dovrebbe essere davvero raro che il client effettui una richiesta che si trova su un server senza una sessione valida. Inoltre, ciò significa che puoi creare un messaggio "la tua sessione è scaduto" avviato dal cliente. –