Django中基于令牌的身份验证

时间:2011-02-17 00:14:43

标签: django

我正在尝试找出在我的django应用程序中实现基于令牌的身份验证的最佳方法。一个外部的非django应用程序正在设置一个带有令牌的cookie,我有一个可以根据该令牌检索用户信息的web服务。如果用户设置了cookie,则他们不需要在我的站点上进行身份验证,并且应该根据Web服务传回的信息自动登录。在我看来,有几个不同的选项来执行实际检查,我不确定哪个是最好的:

  1. 编写一个自定义装饰器,如此snippet中的装饰器,而不是使用它 login_required
  2. 通过ajax调用在base_site中调用自定义身份验证方法。在每个页面上,都会进行检查,如果cookie存在且有效,则用户将自动登录。
  3. 将一些javascript添加到LOGIN_REDIRECT_URL页面,该页面将检查/验证ajax调用中的cookie,并在cookie经过身份验证时自动重定向回引用者。
  4. 我有遗失的选择吗?理想情况下,有一种方法可以将其构建到login_required,而无需编写自定义装饰器。

1 个答案:

答案 0 :(得分:20)

在搜索代码之前,请务必阅读文档。 http://docs.djangoproject.com/en/1.2/topics/auth/#other-authentication-sources 另请阅读提供的Django源代码。

你想创造三件事。

  1. 用于捕获令牌的中间件。这是大多数工作发生的地方。它检查令牌,对其进行身份验证(通过身份管理器确认),然后登录用户。

  2. 验证后端以查找用户。这是一个存根。它所做的就是根据需要创建用户。您的身份管理员有详细信息。您只是在Django的本地数据库上缓存当前版本的用户。

  3. 这是中间件(已编辑)。

    from django.contrib.auth import authenticate, login
    
    class CookieMiddleware( object ):
        """Authentication Middleware for OpenAM using a cookie with a token.
        Backend will get user.
        """
        def process_request(self, request):
            if not hasattr(request, 'user'):
                raise ImproperlyConfigured() 
            if "thecookiename" not in request.COOKIES:
                return
            token= request.COOKIES["thecookiename"]
            # REST request to OpenAM server for user attributes.
            token, attribute, role = identity_manager.get_attributes( token )
            user = authenticate(remote_user=attribute['uid'][0])
            request.user = user
            login(request, user)
    

    identity_manager.get_attributes是我们编写的一个单独的类,用于验证令牌并从IM源获取用户的详细信息。当然,这必须用于测试目的。

    这是后端(已编辑)

    class Backend( RemoteUserBackend ):
        def authenticate(**credentials):
            """We could authenticate the token by checking with OpenAM
            Server.  We don't do that here, instead we trust the middleware to do it.
            """
            try:
                user= User.objects.get(username=credentials['remote_user'])
            except User.DoesNotExist:
                user= User.objects.create(username=credentials['remote_user'] )
            # Here is a good place to map roles to Django Group instances or other features.
            return user
    

    这不会对装饰器进行实质性更改以进行身份​​验证或授权。

    为了确保这一点,我们实际上刷新了我们的用户和组信息 身份管理员。

    请注意,中间件会针对每个请求运行。有时,可以将令牌传递给支持的authenticate方法。如果令牌存在于本地用户DB中,则请求可以在不联系身份管理器的情况下继续。

    然而,我们在身份管理器中有复杂的规则和超时,因此我们必须检查每个令牌以确保它是有效的。一旦中间件确定令牌有效,我们就可以允许后端进行任何其他处理。

    这不是我们的实时代码(做一个好例子有点太复杂了。)