我正在尝试使用 Django 实现具有过滤资源访问(OAuth 身份验证)的 Web 服务,但我有几个问题。
我创建了两个网络服务器:
- http://localhost:8080:Web 服务提供者(使用 django-piston 进行 Web 服务)
- http://localhost:8000 : 网络服务消费者
我正在尝试使用 1.0a 版的 OAuth 来针对提供者对消费者进行身份验证。此处描述了此协议的工作流程。
简而言之,以下是不同的步骤(交换的资源的名称):
- 消费者向提供者请求令牌(密钥、秘密)
- 如果消费者有效,则提供者返回一个令牌(oauth_token,oauth_token_secret)
- 消费者将用户重定向到提供者以登录/授予访问权限(oauth_token)
- 用户授予消费者对资源的访问权限。
- 提供者给消费者一个令牌验证器(token_verifier)
- 消费者请求一个 access_token (key , secret, oauth_token, oauth_token_secret, oauth_verifier)
- 提供者给消费者一个 access_token (oauth_token)
- 消费者使用其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 问题
- 消费者应该拥有多少代币?一?每个用户一个?每个资源一个?
- 消费者应该如何存储其令牌?
- 您如何指定消费者可以使用其令牌访问哪些资源?在将用户重定向到服务提供者(第 3 步)时,消费者是否应该能够提供它想要访问的资源的 ID?
- 如果消费者想要访问用户过去已经授予访问权限的资源,它是否应该将用户重定向到服务提供者(并让服务提供者立即返回 oauth_verifier,而不是请求用户许可) ?
技术问题
现在,我正在使用本地内存缓存会话来存储令牌,但它不起作用:
- 当会话在消费者服务器上激活时,用户每次都必须在服务提供者服务器上登录(即使他已经登录)。
- 在第一个视图(请求令牌)中,我将
oauth_token
and存储oauth_token_secret
在请求的会话中。当我尝试在第二个视图中访问它时(在重定向用户之前),它可以工作。但是当我尝试在最后一个视图中访问它时(重定向之后)它没有(在字典KeyError
中oauth_token
找不到)request.session
谢谢!