python - check_password - login url django
Django: ¿señal cuando el usuario inicia sesión? (8)
Además de @PhoebeB respuesta: también puedes usar @receiver
decorator así:
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
@receiver(user_logged_in)
def post_login(sender, user, request, **kwargs):
...do your stuff..`
Y si lo pones en signals.py
en tu directorio de aplicación, entonces app.py
a app.py
:
def ready(self):
import app_name.signals`
En mi aplicación Django, necesito comenzar a ejecutar algunos trabajos de fondo periódicos cuando un usuario inicia sesión y deja de ejecutarlos cuando el usuario cierra la sesión, por lo que estoy buscando una manera elegante de
- ser notificado de un inicio / cierre de sesión de usuario
- consultar estado de inicio de sesión de usuario
Desde mi punto de vista, la solución ideal sería
- una señal enviada por cada
django.contrib.auth.views.login
y... views.logout
- un método
django.contrib.auth.models.User.is_logged_in()
, análogo a... User.is_active()
o... User.is_authenticated()
Django 1.1.1 no tiene eso y soy reacio a parchar la fuente y agregarla (no estoy seguro de cómo hacer eso, de todos modos).
Como solución temporal, agregué un campo booleano is_logged_in
al modelo UserProfile que se borra de manera predeterminada, se configura la primera vez que el usuario LOGIN_REDIRECT_URL = ''/''
la página de destino (definido por LOGIN_REDIRECT_URL = ''/''
) y se consulta en solicitudes posteriores. Lo agregué a UserProfile, por lo que no tengo que derivar y personalizar el modelo de Usuario incorporado solo para ese propósito.
No me gusta esta solución. Si el usuario hace clic explícitamente en el botón de cerrar sesión, puedo borrar el indicador, pero la mayoría de las veces, los usuarios simplemente abandonan la página o cierran el navegador; limpiar la bandera en estos casos no me parece sencillo. Además (eso es más bien nitidez de modelo de datos), is_logged_in
no pertenece al is_logged_in
usuario, sino al modelo de usuario.
¿Alguien puede pensar en enfoques alternativos?
Idea aproximada: podrías usar middleware para esto. Este middleware podría procesar solicitudes y emitir señal cuando se solicite una URL relevante. También podría procesar las respuestas y la señal de fuego cuando la acción dada realmente sucedió.
Inferir el cierre de sesión, en lugar de tener que hacer clic explícitamente en un botón (lo que nadie hace), significa elegir una cantidad de tiempo de inactividad que equivale a "desconectado". phpMyAdmin usa un valor predeterminado de 15 minutos, algunos sitios bancarios usan tan solo 5 minutos.
La forma más sencilla de implementar esto sería cambiar la duración de la cookie. Puede hacer esto para todo su sitio especificando la settings.SESSION_COOKIE_AGE
. Alternativamente, puede cambiarlo por usuario (en base a un conjunto arbitrario de criterios) utilizando HttpResponse.setcookie()
. Puede centralizar este código creando su propia versión de render_to_response()
y haciendo que configure la duración de cada respuesta.
La única forma confiable (que también detecta cuando el usuario ha cerrado el navegador) es actualizar algún campo last_request
cada vez que el usuario carga una página.
También podría tener una solicitud AJAX periódica que haga ping al servidor cada x minutos si el usuario tiene una página abierta.
Luego, tenga un solo trabajo de fondo que obtenga una lista de usuarios recientes, cree trabajos para ellos y borre los trabajos para los usuarios que no estén en esa lista.
Puede usar esto:
from django.contrib.auth.signals import user_logged_out, user_logged_in
@login_required
def user_logout(request):
logout(request)
user_logged_out()
return redirect(''post_list'')
Puedes usar una señal como esta (puse la mía en models.py)
from django.contrib.auth.signals import user_logged_in
def do_stuff(sender, user, request, **kwargs):
whatever...
user_logged_in.connect(do_stuff)
Consulte django docs: https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals y aquí http://docs.djangoproject.com/en/dev/topics/signals/
Una opción podría ser ajustar las vistas de inicio / cierre de sesión de Django con las suyas. Por ejemplo:
from django.contrib.auth.views import login, logout
def my_login(request, *args, **kwargs):
response = login(request, *args, **kwargs)
#fire a signal, or equivalent
return response
def my_logout(request, *args, **kwargs):
#fire a signal, or equivalent
return logout(request, *args, **kwargs)
A continuación, utiliza estas vistas en su código en lugar de Django, y listo.
Con respecto a consultar el estado de inicio de sesión, es bastante simple si tiene acceso al objeto de solicitud; simplemente revise el atributo de usuario de la solicitud para ver si es un usuario registrado o el usuario anónimo, y bingo. Para citar la documentación de Django :
if request.user.is_authenticated():
# Do something for logged-in users.
else:
# Do something for anonymous users.
Si no tiene acceso al objeto de solicitud, entonces será difícil determinar si el usuario actual está conectado.
Editar:
Desafortunadamente, nunca podrás obtener la funcionalidad User.is_logged_in()
, es una limitación del protocolo HTTP. Sin embargo, si hace algunas suposiciones, es posible que pueda acercarse a lo que desea.
Primero, ¿por qué no puedes obtener esa funcionalidad? Bueno, no se puede distinguir la diferencia entre alguien que cierra el navegador o alguien que pasa un rato en una página antes de buscar uno nuevo. No hay forma de saber por HTTP cuando alguien realmente abandona el sitio o cierra el navegador.
Entonces, aquí tienes dos opciones que no son perfectas:
- Utilice el evento de
unload
de Javascript para detectar cuando un usuario abandona una página. Sin embargo, debe escribir una lógica cuidadosa para asegurarse de no cerrar la sesión de un usuario cuando aún navega por su sitio. - Inicie la señal de cierre de sesión cada vez que un usuario inicie sesión, solo para estar seguro. Cree también un trabajo cron que se ejecute con bastante frecuencia para eliminar las sesiones caducadas: cuando se elimina una sesión caducada, compruebe que el usuario de la sesión (si no es anónimo) no tiene más sesiones activas, en cuyo caso activa la señal de cierre de sesión.
Estas soluciones son complicadas y no ideales, pero son lo mejor que puedes hacer, desafortunadamente.
una solución rápida para esto sería que, en el _ _ init _ _.py de su aplicación, coloque el siguiente código:
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
@receiver(user_logged_in)
def on_login(sender, user, request, **kwargs):
print(''User just logged in....'')