2009-06-29 99 views
16

我有一个Django应用程序从外部源(通过HTTP查询)获取它的数据。也就是说,我没有选择本地数据库的选项。会话数据存储在缓存中(在我的开发服务器上,我使用的是SQLite数据库,因此它不是错误源)。我使用流血的Django 1.1svn。Django的用户和来自外部来源的认证

输入问题:我想为用户使用Django自己的认证系统。

编写我自己的身份验证后端似乎相当简单,但总是在您有本地数据库保存用户的条件下。没有数据库我的主要问题是持久性。

我用下面的(假设datasource.get()是返回某种字典的功能)试了一下:

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 

但在MYUSER有意遗漏save()方法似乎打破登录的会话存储。

MyUser应该怎么样没有本地数据库?

+4

我刚刚发现 似乎做我想做的。如果我对它进行了评估,我会发布一个答案(不要气馁以添加你自己的;-))。 – Boldewyn 2009-06-29 10:05:36

+0

该链接有一个不好的拖尾'>'... darn。 – Boldewyn 2009-06-29 10:07:18

回答

22

好吧,它比我想象的要复杂得多。首先,从http://docs.djangoproject.com/en/dev/howto/auth-remote-user/开始,但您需要使用自己的后端和用户进行扩展。

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 

然后用户:

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 [] 

唷! Django 确实不适用于没有数据库的情况下...

+1

你在设置文件中有什么改变?我正在尝试这样做,它就像完全忽略了我的远程后端。 – Colleen 2014-11-07 22:32:10

1

grep平源显示,这唯一的地方user.save()实际上是所谓的(除了创建用户和密码管理代码,你并不需要在所有使用)是django.contrib.auth.login(),更新user.last_login值。

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

如果您不希望用户数据在DB休息,尝试添加虚拟save()方法。如果我是对的,它应该起作用。

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

当然,因为你没有持久性可言,你应该考虑缓存datasource.get结果,否则在最坏的情况下,你可能最终会在每一个登录用户的命中一次又一次地查询数据。

4

您可能会断开调用它的信号,而不是覆盖save方法。这是我在一些对用户数据库具有只读权限的应用程序中所做的。

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