2011-02-17 116 views
32

我想弄清楚在我的django應用程序中實現基於令牌的身份驗證的最佳方式。外部非Django應用程序使用令牌設置cookie,並且我有一個可以基於該令牌檢索用戶信息的web服務。如果用戶設置了Cookie,則他們不需要在我的網站上進行身份驗證,並且應該根據Web服務傳回的信息自動登錄。在我看來,有幾個不同的選項來執行實際的檢查,我不知道這是最好的:基於令牌的身份驗證在Django

  1. 寫像在這個snippet的定製的裝飾,並用它來代替 login_required
  2. 通過ajax調用在base_site內調用自定義身份驗證方法。在每一頁上,都會進行檢查,如果cookie存在並且有效,那麼用戶將自動登錄。
  3. LOGIN_REDIRECT_URL頁面添加一些javascript,以便在ajax調用中檢查/驗證Cookie,並且如果cookie經過驗證,會自動重定向回推薦人。

有沒有我缺少的選項?理想情況下,將有一種方法可以將其構建到login_required中,而無需編寫自定義裝飾器。

回答

20

在搜索代碼之前,一定要閱讀文檔。 http://docs.djangoproject.com/en/1.2/topics/auth/#other-authentication-sources 也讀取提供的Django源代碼。

你想創造三件事情。

  1. 捕獲令牌的中間件。這是大部分工作發生的地方。它檢查令牌,驗證它(通過與身份管理器確認),然後登錄用戶。

  2. 身份驗證後端查找用戶。這是一個存根。它所做的只是根據需要創建用戶。您的身份管理器有詳細信息。您只是在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是可以的。如果令牌存在於本地用戶數據庫中,則可以在不聯繫身份管理器的情況下繼續進行請求。

然而,我們在身份管理器中有複雜的規則和超時,所以我們必須檢查每個標記以確保它是有效的。一旦中間件確定令牌有效,我們就可以允許後端執行任何額外的處理。

這不是我們生活的代碼(這是一個有點太複雜,使一個很好的例子。)

+1

後端可以簡化用戶,_ = User.objects.get_or_create(用戶名=憑證[「REMOTE_USER」] ) – 2013-03-07 23:43:10