considerar esta vista de Django que obtendrá una lista de elementos asociados al usuario actual:¿Cuál es la mejor manera de manejar los tiempos de espera de sesión en las solicitudes de 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))
Obviamente, quiere usar el decorador login_required
, para restringir el acceso a la vista para los usuarios registrados.
¿Qué hace login_required
cuando un usuario no autenticado intenta acceder a la vista? Devuelve HttpResponseRedirect
hacia settings.LOGIN_URL
.
consideran este código JavaScript, que llama a la vista:
var getPage = function(pageNumber) {
$.ajax({
url: "/list_items/" + pageNumber + "/",
success: function(data) {
$("#list_container").html(formatData(data))
}
});
};
Supongamos settings.SESSION_COOKIE_AGE = 60
segundos.
Si un usuario va a la página 1, lo lee durante 61 segundos, luego hace clic en el botón de la página 2, login_required
decorador de Django detectará que la sesión ya no está activa, y devolverá un HttpResponseRedirect(settings.LOGIN_URL)
, lo que hará que la success
devolución de llamada para obtener una página de inicio de sesión HTML en lugar de la lista codificada JSON.
This is where it happens.
It's called by user_passes_test
here.
Cuál es la mejor manera de manejar esto?
Aquí hay algunas cosas que he pensado:
1.
La devolución de llamada success
debe comprobar la respuesta, y ver si se pone una página de inicio de sesión, por cualquier medio (comprobar si el tipo de contenido es HTML, comprobar el contenido , etc.) Pero esto significa que tenemos para envolver toda llamadas AJAX con un envoltorio de devolución de llamada de esta manera:
$.ajax({
url: "/list_items/" + pageNumber + "/",
success: sessionExpiryCallbackWrapper(function(data) {
$("#list_container").html(formatData(data))
})
});
pero esto es feo, y los desarrolladores podría olvidarse de hacer esto en todas partes.
2.
Use $.ajaxComplete
para manejar todas las solicitudes.
$.ajaxComplete(globalCompleteCallback);
$.ajax({
success: successCallback,
complete: completeCallback
});
Pero este es el orden de llamada:
successCallback(); // success is called before complete
completeCallback();
globalCompleteCallback(); // this is called after the local callback
Tan solo nos queda coger el redireccionamiento, después successCallback ha fallado, y posiblemente con errores JS debido a los datos no válidos que recibió.
3.
Si login_required
volvería en 403 peticiones 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)
Pero login_required
simplemente utiliza user_passes_test
que no hace esto.
user_passes_test
tiene mucha funcionalidad, por lo que no es una buena idea volver a implementarla.
¿Cuál es la mejor manera de manejar los tiempos de espera para las llamadas AJAX?
Lo siento, pero voy a poner todo en ti filosófico. La intención original de los tiempos de espera de la sesión era evitar que el servidor retuviera recursos significativos o tener que realizar costosas operaciones en cada solicitud. Ahora tenemos frameworks del lado del cliente haciendo la mayor parte del trabajo. Entonces, ¿por qué se necesitan tiempos de espera de sesión cortos? –
@DaveMethvin Los tiempos de espera de sesión son necesarios para reducir la ventana para el secuestro de la sesión, ya sea a) en el cable/aire o b) físicamente por alguien que va a la computadora de otra persona después de haber AFK un poco. – Prody
Ese problema parece bastante fácil de resolver, solo que los tiempos de espera de la sesión del cliente sean más cortos que los del servidor. Si ese es el caso, es muy raro que el cliente haga alguna vez una solicitud que se encuentre en un servidor sin una sesión válida. Además, eso significa que puedes mostrar un mensaje interesante, iniciado por el cliente, "tu sesión ha expirado". –