2011-04-12 70 views
4

我想用Django實現一個具有過濾資源訪問(OAuth認證)的Web服務,我有幾個問題。OAuth Web服務和Django活塞

我創建了兩個Web服務器:

我想使用的版本1.0a的OAuth來驗證消費者對提供商。該協議的工作流程描述如下:here

概括地說,這裏有不同的步驟(資源的名稱交換):

  1. 消費者提供商請求令牌(密鑰,密鑰)
  2. 如果消費者有效,提供商返回一個令牌(oauth_token,oauth_token_secret)
  3. 消費者將用戶重定向到該提供商登錄/准許訪問(組oauth_token)
  4. 用戶許可獲得了消費者的資源。
  5. 提供商消費者令牌驗證(token_verifier)
  6. 消費者請求一個的access_token(鑰匙,祕密,組oauth_token,oauth_token_secret,oauth_verifier)
  7. 提供商消費者 access_token(oauth_token)
  8. 消費者使用其oauth_token訪問資源

這裏是我的消費者的意見代碼:

from django.shortcuts import render_to_response 
from django.http import HttpResponse, HttpResponseRedirect 
import oauth2 as oauth 
import urlparse 

REQUEST_TOKEN_URL = 'http://127.0.0.1:8080/api/authentication/request_token/' 
AUTHORIZATION_URL = 'http://127.0.0.1:8080/api/authentication/authorize/' 
ACCESS_TOKEN_URL = 'http://127.0.0.1:8080/api/authentication/access_token/' 
CONSUMER_CALLBACK_URL = 'http://127.0.0.1:8000/request_access_token/' 

CONSUMER_KEY = 'key' 
CONSUMER_SECRET = 'secret' 

consumer = oauth.Consumer(CONSUMER_KEY, CONSUMER_SECRET) 
client = oauth.Client(consumer) 

def request_token(request): 
    """ 
    Contacts the service provider to get a token. 
    """ 
    resp, content = client.request(REQUEST_TOKEN_URL, 'GET') 
    oauth_token = dict(urlparse.parse_qsl(content)).get('oauth_token', None) 
    oauth_token_secret = dict(urlparse.parse_qsl(content)).get('oauth_token_secret', 
                  None) 

    if oauth_token is None: 
     return render_to_response('home.html', {'data': 'NO TOKEN FOUND'}) 
    else: 
     request.session['oauth_token'] = oauth_token 
     request.session['oauth_token_secret'] = oauth_token_secret 
     return HttpResponseRedirect('request_user_permission/') 

def request_user_permission(request): 
    """ 
    Redirects the user to the service provider to get permission if 
    token provided. 
    """ 
    oauth_token = request.session['oauth_token'] 

    if oauth_token is None: 
     return render_to_response('home.html', {'data': 'NO TOKEN FOUND'}) 
    else: 
     return HttpResponseRedirect("%s?oauth_token=%s&oauth_callback=%s" 
      % (AUTHORIZATION_URL, oauth_token, CONSUMER_CALLBACK_URL)) 


def request_access_token(request): 
    """ 
    Requests an access token from the service provider 
    if the user granted permission. 
    """ 
    error = request.GET.get('error', None) 

    if error is None: 
     oauth_verifier = request.GET.get('oauth_verifier', None) 

     if oauth_verifier is None: 
      return render_to_response('home.html', 
             {'data': 'UNKNOWN ERROR HAPPENED'}) 
     else: 
      # User permission granted, requesting access token 
      oauth_token = request.session['oauth_token'] 
      oauth_token_secret = request.session['oauth_token_secret'] 

      token = oauth.Token(oauth_token, oauth_token_secret) 
      token.set_verifier(oauth_verifier) 
      client.token = token 

      resp, content = client.request(ACCESS_TOKEN_URL, 'POST') 
      access_token = dict(urlparse.parse_qsl(content)) 
      return render_to_response('home.html', {'data': access_token}) 
    else: 
     return render_to_response('home.html', {'data': error}) 

一般OAuth的問題

  • 消費者應該有多少令牌呢?一?每個用戶一個?每個資源一個?
  • 消費者應該如何存儲其令牌?
  • 如何指定消費者可以使用其令牌訪問哪些資源?消費者不應該在將用戶重定向到服務提供商時提供想要訪問的資源的ID(步驟3)?
  • 如果消費者想要訪問用戶已經爲其授予訪問權限的資源,是否應該將用戶重定向到服務提供者(並讓服務提供者立即返回oauth_verifier,而不是詢問用戶許可)?

技術問題

現在,我使用本地內存中緩存的會話存儲令牌,但它不工作:

  • 當會話對消費者激活服務器,用戶必須每次都在服務提供商服務器上登錄(即使他已經登錄)。
  • 在第一個視圖(請求令牌)中,我將oauth_tokenoauth_token_secret存儲在請求的會話中。當我嘗試在第二個視圖中訪問它時(在重定向用戶之前),它可以工作。但是,當我嘗試訪問它在最後一個視圖(重定向後)不(KeyErroroauth_token沒有在request.session字典中找到)

謝謝!

回答

1

我在同一條船上(使用OAuth身份驗證實現API),並且在我的研究中遇到了django-oauth-plus項目。本教程很好地介紹了鏈接到的圖表中概述的過程的每個步驟。代碼本身似乎是一個相當完整的OAuth實現(不知道我是否知道我在說什麼,只是學習這些東西)。

另外,this guy有一個關於OAuth基礎知識的非常好的教程(我對此感到困惑)。