我正在尝试找出在我的django应用程序中实现基于令牌的身份验证的最佳方法。一个外部的非django应用程序正在设置一个带有令牌的cookie,我有一个可以根据该令牌检索用户信息的web服务。如果用户设置了cookie,则他们不需要在我的站点上进行身份验证,并且应该根据Web服务传回的信息自动登录。在我看来,有几个不同的选项来执行实际检查,我不确定哪个是最好的:
login_required
。 LOGIN_REDIRECT_URL
页面,该页面将检查/验证ajax调用中的cookie,并在cookie经过身份验证时自动重定向回引用者。我有遗失的选择吗?理想情况下,有一种方法可以将其构建到login_required
,而无需编写自定义装饰器。
答案 0 :(得分:20)
在搜索代码之前,请务必阅读文档。 http://docs.djangoproject.com/en/1.2/topics/auth/#other-authentication-sources 另请阅读提供的Django源代码。
你想创造三件事。
用于捕获令牌的中间件。这是大多数工作发生的地方。它检查令牌,对其进行身份验证(通过身份管理器确认),然后登录用户。
验证后端以查找用户。这是一个存根。它所做的就是根据需要创建用户。您的身份管理员有详细信息。您只是在Django的本地数据库上缓存当前版本的用户。
这是中间件(已编辑)。
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中,则请求可以在不联系身份管理器的情况下继续。
然而,我们在身份管理器中有复杂的规则和超时,因此我们必须检查每个令牌以确保它是有效的。一旦中间件确定令牌有效,我们就可以允许后端进行任何其他处理。
这不是我们的实时代码(做一个好例子有点太复杂了。)