Django用户和外部源的身份验证

时间:2009-06-29 08:17:47

标签: database django authentication

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

输入问题:我想为用户使用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应该怎么样?

3 个答案:

答案 0 :(得分:23)

好的,它比我想象的要复杂得多。首先,从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 :(得分: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)

答案 2 :(得分:1)

grep ping来源显示,实际调用的唯一地方user.save()(除了用户创建和密码管理代码,你完全不需要使用)是{{1更新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() 方法。如果我是对的,它应该有用。

save()

当然,因为你根本没有持久性,你应该考虑缓存def save(self, *args, **kwargs): pass 结果,否则在最坏的情况下,你可能会在每个登录用户的命中时反复查询数据。