2009-05-04 8 views
21

Quiero permitir solo una sesión autenticada a la vez para un inicio de sesión individual en mi aplicación Django. Entonces, si un usuario inicia sesión en la página web en una dirección IP determinada, y esas mismas credenciales de usuario se usan para iniciar sesión desde una dirección IP diferente, quiero hacer algo (desconectar al primer usuario o denegar el acceso al segundo usuario)¿Cómo puedo detectar varios inicios de sesión en una aplicación web de Django desde diferentes ubicaciones?

Respuesta

18

No estoy seguro si esto sigue siendo necesaria, pero pensé que podría compartir mi solución:

1) Instalar Django-tracking (gracias para que la punta de Van Gale Google Maps + GeoIP es increíble!)

2) Añadir este middleware:

from django.contrib.sessions.models import Session 
from tracking.models import Visitor 
from datetime import datetime 

class UserRestrictMiddleware(object): 
    """ 
    Prevents more than one user logging in at once from two different IPs 
    """ 
    def process_request(self, request): 
     ip_address = request.META.get('REMOTE_ADDR','') 
     try: 
      last_login = request.user.last_login 
     except: 
      last_login = 0 
     if unicode(last_login)==unicode(datetime.now())[:19]: 
      previous_visitors = Visitor.objects.filter(user=request.user).exclude(ip_address=ip_address) 
      for visitor in previous_visitors: 
       Session.objects.filter(session_key=visitor.session_key).delete() 
       visitor.user = None 
       visitor.save() 

3) Asegúrese de que va después de la VisitorTrackingMiddleware y usted debe encontrar los inicios de sesión anteriores es golpeado de forma automática cuando alguien nuevo en los registros :)

+0

¿Podemos confiar en django-tracking después de todos estos años de inactividad? – NikosKeyz

6

Tendrá que hacer esto con middleware personalizado.

En el método de middleware process_request() tendrá acceso al objeto pedido, por lo que puede hacer algo como lo siguiente:

session_key = request.session.session_key 
ip_address = request.META.get('REMOTE_ADDR', '') 

Ahora se conoce la dirección IP, a fin de comprobar un modelo que cree que (más o menos) se vería así:

class SessionIPS(models.Model): 
    session = models.ForeignKey(Session) 
    IP = models.CharField(max_length=20) 

Así que cuando se crea o se elimina va modifiy tabla de la sesión de IP en consecuencia una sesión, y cuando llega una solicitud asegurarse de que la dirección IP no está siendo usado para otra sesión. Si es así, devuelva un Http404 (o algo similar) del middleware.

Una aplicación conectable que puede mostrarle muchos más detalles (e incluso incluye la dirección IP en su propio modelo) es django-tracking.

6

Django's middleware probablemente lo ayuden a conseguirlo. El problema es que probablemente desee permitir varias sesiones anónimas desde la misma dirección IP, incluso sesiones autenticadas para diferentes usuarios, pero no sesiones autenticadas para el mismo usuario.

Querrá:

  1. crear un modelo de perfil de usuario para almacenar la dirección IP de la última entrada de un usuario. Consulte la documentación de Django Storing additional information about users.

  2. Implemente un custom authentication backend. Este backend, cuando se activa y autentica correctamente a un usuario (simplemente llame a super) borrará la última IP de inicio de sesión del usuario en el modelo de perfil.

  3. Implemente una subclase de la clase django.contrib.sessions.SessionMiddleware de Django. Implementar process_request. Si el modelo de perfil del objeto request.user no tiene una dirección IP, configúrelo y permita la solicitud. Si tiene una dirección IP y la dirección IP es diferente de la dirección IP de la solicitud actual (request.META.REMOTE_ADDR), haga lo que desee para cerrar la sesión del otro usuario o devolver un error al solicitante.

  4. Actualice su archivo settings.py para que su back-end de autenticación personalizado se procese primero y para que su middleware de sesión personalizada también se procese primero. Esto implica la actualización de settings.AUTHENTICATION_BACKENDS y settings.MIDDLEWARE_CLASSES.

9

Si' ya estamos usando Django de seguimiento como se sugiere aquí, hay una manera mucho más fácil de implementar esto:

definir un manejador de señales:

# myapp/signals.py 
def kick_my_other_sessions(sender, request=None, user=None, **kwargs): 
    from tracking.models import Visitor 
    from django.contrib.sessions.models import Session 
    keys = [v.session_key for v in Visitor.objects.filter(user=request.user).exclude(session_key=request.session.session_key)] 
    Session.objects.filter(session_key__in=keys).delete() 

Crear un oyente para la señal user_logged_in:

# myapp/__init__.py 
from myapp.signals import kick_my_other_sessions 
from django.contrib.auth.signals import user_logged_in 
user_logged_in.connect(kick_my_other_sessions, sender=User) 

Esto instituir una especie de "último usuario para iniciar sesión victorias" del sistema. Si desea permitir múltiples inicios de sesión por el mismo usuario desde la misma ip, puede agregar un .exclude() a la búsqueda Visitors.

+0

También es útil establecer 'visitor.user = None' para cada uno de los visitantes coincidentes; de lo contrario, este código aún encontrará visitantes para sesiones ya eliminadas en cada inicio de sesión. (Esto es importante si decide agregar un mensaje para indicarle al usuario recién conectado 'acaba de cerrar sesión en otra sesión'). – Duncan

Cuestiones relacionadas