OAuth Web 服务和 Django 活塞
我正在尝试使用 Django 实现具有过滤资源访问(OAuth 身份验证)的 Web 服务,但我有几个问题。
我创建了两个网络服务器:
- http://localhost:8080 :Web 服务提供者(使用 django-piston 作为 Web 服务)
- http://localhost:8000 :Web 服务使用者
我正在尝试使用 OAuth 1.0a 版本来针对提供者对使用者进行身份验证。 此处描述了该协议的工作流程。
简而言之,以下是不同的步骤(交换的资源的名称):
- 消费者从提供者请求令牌(密钥、秘密)
- 如果消费者有效,提供者返回一个令牌(oauth_token,oauth_token_secret)
- 消费者将用户重定向到提供者登录/授予访问权限 (oauth_token)
- 用户向使用者授予对资源的访问权限。
- 提供者给消费者一个令牌验证器(token_verifier)
- 消费者请求一个access_token(key、secret、oauth_token、oauth_token_secret、oauth_verifier)
- < Strong>provider 为 consumer 提供 access_token (oauth_token)
- consumer 使用其 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})
< strong>一般 OAuth 问题
- 消费者应该拥有多少个令牌?一?每个用户一个?每个资源一个?
- 消费者应该如何存储其令牌?
- 如何指定消费者可以使用其令牌访问哪些资源?在将用户重定向到服务提供商时(步骤 3),消费者是否应该能够提供其想要访问的资源的 id?
- 如果消费者想要访问用户过去已经授予访问权限的资源,是否应该将用户重定向到服务提供商(并让服务提供商立即返回 oauth_verifier,而不是询问用户许可) ?
技术问题
现在,我正在使用本地内存缓存会话来存储令牌,但它不起作用:
- 当在消费者服务器上激活会话时,用户每次都必须登录服务提供商服务器(即使他已经登录)。
- 在第一个视图(请求令牌)中,我将
oauth_token
和oauth_token_secret
存储在请求的会话中。当我尝试在第二个视图中访问它(在重定向用户之前)时,它起作用了。但是,当我尝试在最后一个视图中(重定向后)访问它时,它没有(KeyError
,在request.session< 中找不到
oauth_token
/code> 字典)
谢谢!
I am trying to implement a web service with filtered resources access (OAuth authentication) with Django and I had a couple of questions.
I created two webservers:
- http://localhost:8080 : Web Service Provider (using django-piston for the webservice)
- http://localhost:8000 : Web Service Consumer
I am trying to use the version 1.0a of OAuth to authenticate the consumer against the provider. The workflow of this protocol is described here.
In a nutshell, here are the different steps (name of the resource exchanged):
- The consumer requests a token from the provider (key, secret)
- If the consumer is valid, the provider returns it a token (oauth_token, oauth_token_secret)
- The consumer redirects the User to the provider to login/grant access (oauth_token)
- The user grant access to the consumer for the resource.
- The provider gives the consumer a token verifier (token_verifier)
- The consumer requests an access_token (key, secret, oauth_token, oauth_token_secret, oauth_verifier)
- The provider gives the consumer an access_token (oauth_token)
- The consumer uses its oauth_token to access the resource
Here is the code of the views of my consumer:
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})
General OAuth Questions
- How many token should the consumer have? One? One per User? One per Resource?
- How is the consumer supposed to store its token(s)?
- How do you specify which resources the consumer can access with its token? Shouldn't the consumer be able to provide the id of the resource it wants to get access to when redirecting the user to the service provider (step 3)?
- If a consumer wants to access a resource for which the user has already granted the access in the past, should it redirect the user to the service provider anyway (and let the service provider return the oauth_verifier instantly, instead of asking the User for permission)?
Technical problems
Right now, I am using local memory cached sessions to store the token, but it doesn't work:
- When the sessions are activated on the consumer server, the User has to login every time on the service provider server (even if he was already logged in).
- In the first view (requesting the token) I store the
oauth_token
andoauth_token_secret
in the request's session. When I try to access it in the second view (before redirecting the user), it works. But when I try to access it in the last view (after the redirection) it doesn't (KeyError
,oauth_token
is not found in therequest.session
dictionary)
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我在同样的船上(使用 OAuth 身份验证实现 API),并且遇到了 django-oauth-plus 我研究中的项目。本教程很好地完成了您链接到的图表中概述的过程的每个步骤。代码本身似乎是 OAuth 的相当完整的实现(不确定我是否知道我在说什么,只是学习这些东西)。
另外,这个人 有一个关于 OAuth 基础知识的非常好的教程(我对此很挣扎)。
I'm in the same-ish boat (implementing an API with OAuth authentication), and I came across the django-oauth-plus project in my research. The tutorial does a good job of walking through each step of the process outlined in the diagram you linked to. The code itself seems a pretty complete implementation of OAuth (not sure if I know what I'm talking about tho, just learning this stuff).
Also, this guy has a pretty great tutorial about the basics of OAuth (I struggled with that).