OAuth веб-сервис и Django-поршень - PullRequest
4 голосов
/ 12 апреля 2011

Я пытаюсь реализовать веб-сервис с фильтрованным доступом к ресурсам (аутентификация OAuth) с помощью Django, и у меня возникла пара вопросов.

Я создал два веб-сервера:

Я пытаюсь использовать версию1.0a OAuth для аутентификации потребителя против провайдера.Рабочий процесс этого протокола описан здесь .

В двух словах, здесь описаны различные этапы (имя обмененного ресурса):

  1. потребитель запрашивает токен у поставщика (ключ, секрет)
  2. Если потребитель действителен, поставщик возвращает еготокен (oauth_token, oauth_token_secret)
  3. Потребитель перенаправляет пользователя к поставщику для входа / предоставления доступа (oauth_token)
  4. The пользователь предоставляет доступ к ресурсу для потребителя.
  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

  • Сколько токенов должен иметь потребитель?Один?Один на пользователя?Один на ресурс?
  • Как потребитель должен хранить свой токен (ы)?
  • Как указать, к каким ресурсам потребитель может получить доступ с помощью своего токена?Разве потребитель не может предоставить идентификатор ресурса, к которому он хочет получить доступ, при перенаправлении пользователя на поставщика услуг (шаг 3)?
  • Если потребитель хочет получить доступ к ресурсу, для которогопользователь уже предоставил доступ в прошлом, должен ли он в любом случае перенаправить пользователя к поставщику услуг (и позволить поставщику услуг немедленно вернуть oauth_verifier вместо того, чтобы запрашивать разрешение у пользователя)?

Технические проблемы

Сейчас я использую кэшированные сеансы локальной памяти для хранения токена, но он не работает:

  • Когда сеансы активированы вна потребительском сервере Пользователь должен каждый раз входить в систему на сервере поставщика услуг (даже если он уже вошел в систему).
  • В первом представлении (запрашивая токен) я сохраняю oauth_token и oauth_token_secret в сеансе запроса.Когда я пытаюсь получить доступ к нему во втором представлении (перед перенаправлением пользователя), это работает.Но когда я пытаюсь получить доступ к нему в последнем представлении (после перенаправления), его нет (KeyError, oauth_token не найдено в словаре request.session)

Спасибо!

1 Ответ

1 голос
/ 05 июля 2011

Я в той же лодке (реализую API с аутентификацией OAuth), и я наткнулся на проект django-oauth-plus в своем исследовании.Учебное пособие проделывает хорошую работу по прохождению каждого шага процесса, описанного в диаграмме, с которой вы связаны.Сам код кажется довольно полной реализацией OAuth (не уверен, что я знаю, о чем говорю, просто изучаю этот материал).

Кроме того, у этого парня довольно большойучебник об основах OAuth (я боролся с этим).

...