2009-06-29 11 views
16

Tengo una aplicación de Django que obtiene sus datos completamente de una fuente externa (consultada a través de HTTP). Es decir, no tengo la opción de una base de datos local. Los datos de sesión se almacenan en la memoria caché (en mi servidor de desarrollo utilizo una base de datos SQLite, por lo que no es fuente de error). Estoy usando el borde sangriento Django 1.1svn.Usuarios de Django y autenticación de fuente externa

Ingrese el problema: Deseo utilizar el propio sistema de autenticación de Django para los usuarios.

Parece bastante simple escribir mi propio Authentication Backend, pero siempre bajo la condición de que tenga una base de datos local donde guardar los usuarios. Sin base de datos, mi principal problema es la persistencia.

he probado con los siguientes (asumir que datasource.get() es una función que devuelve algún tipo de dict):

class ModelBackend (object): 
    """Login backend.""" 

    def authenticate (self, username=None, password=None): 
     """Check, if a given user/password combination is valid""" 

     data = datasource.get ('login', username, password) 
     if data and data['ok']: 
      return MyUser (username=username) 
     else: 
      raise TypeError 
      return None 

    def get_user (self, username): 
     """get data about a specific user""" 

     try: 
      data = datasource.get ('userdata', username) 
      if data and data['ok']: 
       return data.user 
     except: 
      pass 
     return None 


class MyUser (User): 
    """Django user who isn't saved in DB""" 

    def save (self): 
     return None 

Pero el save() método intencionada falta de MyUser parece romper el almacenamiento de sesión de un inicio de sesión.

¿Cómo debería ser MyUser sin una base de datos local?

+4

acabo de encontrar parece hacer lo que quiera. Si lo he evaluado, publicaré una respuesta (no se desanime para agregar el suyo ;-)). – Boldewyn

+0

El enlace tiene un '>' ... maldito rastreador. – Boldewyn

Respuesta

22

OK, es mucho más complicado de lo que pensaba. En primer lugar, comience con http://docs.djangoproject.com/en/dev/howto/auth-remote-user/, pero deberá extenderlo con su propio servidor y usuario.

from django.contrib.auth.backends import RemoteUserBackend 

class MyRemoteUserBackend (RemoteUserBackend): 
    # Create a User object if not already in the database? 
    create_unknown_user = False 

    def get_user (self, user_id): 
     user = somehow_create_an_instance_of (MyUser, user_id) 
     return user 

    def authenticate (self, **credentials): 
     check_credentials() 
     user = somehow_create_an_instance_of (MyUser, credentials) 
     return user 

continuación, el usuario:

from django.contrib.auth.models import User 

class MyUser (User): 

    def save (self): 
     """saving to DB disabled""" 
     pass 

    objects = None # we cannot really use this w/o local DB 

    username = "" # and all the other properties likewise. 
        # They're defined as model.CharField or similar, 
        # and we can't allow that 

    def get_group_permissions (self): 
     """If you don't make your own permissions module, 
      the default also will use the DB. Throw it away""" 
     return [] # likewise with the other permission defs 

    def get_and_delete_messages (self): 
     """Messages are stored in the DB. Darn!""" 
     return [] 

Uf! Django realmente no está diseñado para el uso sin una base de datos ...

+1

¿Qué tienes que cambiar en tu archivo de configuración? Estoy tratando de hacer esto y es como si estuviera ignorando completamente mi backend remoto. – Colleen

+1

¿Ha establecido algo a lo largo de 'AUTHENTICATION_BACKENDS = ( 'myapp.MyappUserBackend', )'? – Boldewyn

+0

Sí.Lo descubrí, necesitaba extender el middleware auth remoto en mi caso porque estaba pasando las credenciales de manera diferente a la predeterminada. – Colleen

1

grep la fuente de ping mostró, que el único lugar user.save() se llama en realidad (a excepción de la creación del usuario y el código de gestión de contraseñas, lo que no es necesario utilizar en absoluto) es django.contrib.auth.login(), para actualizar user.last_login valor.

# TODO: It would be nice to support different login methods, like signed cookies. 
user.last_login = datetime.datetime.now() 
user.save() 

Si no desea que los datos del usuario para descansar en la base de datos, intente agregar ficticia método save(). Si estoy en lo correcto, debería funcionar.

def save(self, *args, **kwargs): 
    pass 

Por supuesto, ya que no tienen persistencia en absoluto, usted debe considerar el almacenamiento en caché datasource.get resultados, si no en peor de los casos se puede terminar la consulta de datos y otra vez en todos y cada uno conectado hit de usuario.

4

en lugar de sobrescribir el método save, también puede desconectar la señal que invoca. Esto es lo que hago en algunas aplicaciones que tienen acceso de solo lectura a la base de datos de usuarios.

# models.py (for instance) 
from django.contrib.auth.models import update_last_login, user_logged_in 
user_logged_in.disconnect(update_last_login) 
+0

Estoy trabajando con Django 1.6 y OP + ¡esto me salvó la vida! ¡Gracias! – enpenax

Cuestiones relacionadas