Подписание запросов в Python для OAuth - PullRequest
4 голосов
/ 26 января 2010

В настоящее время я взаимодействую с Twitter API, используя протокол OAuth, и пишу код на Python. Как и большинство пользователей, я думаю, что самая трудная часть спецификаций связана с подписями.

После того, как я бродил по сети в поисках решения, я решил поискать свой собственный код, чтобы лучше понять, что происходит.

Ради других пользователей я публикую здесь очень простую и короткую реализацию спецификаций подписи SHA1 в Python:

import hmac

from hashlib import sha1
from urllib import quote, urlencode
from base64 import b64encode
from urlparse import urlparse

def sign_request_sha1(url,method,data,secret=""):
  pu = urlparse(urlparse(url).geturl())

  normUrl = "%s://%s%s%s" % (
      pu.scheme,
      pu.hostname,
      "" if not pu.port or {"http":80,"https":443}[pu.scheme] == pu.port else ":%d" % pu.port,
      pu.path,
                            )

  names = data.keys()
  names.sort()

  sig = "%s&%s&%s" % (
          method.upper(),
          quote(normUrl,''),
          quote("&".join(["%s=%s" % (k,quote(data[k].encode('utf-8'),'')) for k in names]),''),
                     )

  key = "%s&%s" % (quote(CONSUMER_SECRET.encode('utf-8'),''),secret)

  return b64encode(hmac.new(key,sig,sha1).digest())

Входные параметры для функции:

  • url: URL, который вы собираетесь вызвать для конкретного запроса OAuth.
  • метод: это должно быть "GET" или "POST" в зависимости от того, как вы собираетесь отправить запрос.
  • data: словарь, содержащий все параметры запросов, включая любые пользовательские аргументы, но исключая "oauth_signature" (по понятным причинам).
  • секрет: секретный токен, полученный вами на начальном этапе протокола.

Я протестировал его в Twitter, и он, кажется, работает, но я хотел бы получить некоторые комментарии об ошибках, улучшениях и т. Д.

Наконец, здесь вы найдете фрагмент кода, вызывающий код для начальной фазы «маркера запроса»:

from random import getrandbits
from base64 import b64encode
from time import time

def twitter_request_token(req,callback,errback):
  req_url="http://twitter.com:80/oauth/request_token"

  data = { \
    "oauth_consumer_key" : CONSUMER_KEY,
    "oauth_nonce" : b64encode("%0x" % getrandbits(256))[:32],
    "oauth_timestamp" : str(int(time())),
    "oauth_signature_method" : "HMAC-SHA1",
    "oauth_version" : "1.0",
    "oauth_callback" : "http://localhost:8080/",
         }

  data["oauth_signature"] = sign_request_sha1(req_url,"GET",data)

Спасибо.

1 Ответ

3 голосов
/ 29 января 2010

Моя реакция коленного рефлекса на это Если вы вводите буквы A-E-S в свой код, значит, вы делаете это неправильно . Или, как redditor Хафра недавно напомнил нам о сицилийской версии :

Ха-ха .. ты дурак! Вы стали жертвой одной из классических ошибок. Самым известным из них является: Никогда не ввязывайтесь в сухопутную войну в Азии. Но только немного менее известным является следующее: никогда не пытайтесь свернуть свое собственное шифрование, когда есть хорошо протестированная библиотека, которая сделает это лучше!

Я имею в виду, я понял. Когда я посмотрел в первый раз, oauth.py меня тоже не впечатлил. С тех пор было проделано много работы, и она выглядит лучше, но, похоже, тестов пока нет, поэтому я не знаю. В любом случае, тесты или тесты отсутствуют, они проверены и используются большим количеством людей, чем ваш код.

Но это только то, что я беспокоюсь по поводу повторного использования крипто-кода и на самом деле не помогает вам понять механизм протокола. Это выглядит нормально для меня, но в последнее время я не слишком задумывался о спецификации OAuth.

Просто используйте еще несколько строк для этого pu.port бизнеса; с условным выражением if, выражением or и конструкцией {}[] в одной строке действительно трудно читать.

Если вы действительно хотите пересмотреть код людьми, знакомыми с протоколом, вам, вероятно, лучше спросить список рассылки . И если вы сможете предложить им альтернативный API, который сделает код в их хранилище более привлекательным для новых пользователей, это будет хорошо для всех.

...