Проблемы с авторизацией в Yahoo BOSS V2 - PullRequest
8 голосов
/ 23 июля 2011

У меня ужасно трудные времена с аутентификацией / авторизацией Yahoo.Я включил BOSS в своей учетной записи, настроил способ оплаты, и теперь я пытаюсь запустить поиск по коду Python:

import urllib2
import oauth2 as oauth
import time

OAUTH_CONSUMER_KEY = "blahblahblah"
OAUTH_CONSUMER_SECRET = "blah"

def oauth_request(url, params, method="GET"):
    params['oauth_version'] = "1.0",
    params['oauth_nonce'] = oauth.generate_nonce(),
    params['oauth_timestamp'] = int(time.time())

    consumer = oauth.Consumer(key=OAUTH_CONSUMER_KEY,
                              secret=OAUTH_CONSUMER_SECRET)
    params['oauth_consumer_key'] = consumer.key
    req = oauth.Request(method=method, url=url, parameters=params)
    req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None)

    return req


if __name__ == "__main__":
    url = "http://yboss.yahooapis.com/ysearch/web"

    req = oauth_request(url, params={"q": "cats dogs"})
    req_url = req.to_url()
    print req_url
    result = urllib2.urlopen(req_url)

Я получаю исключение urllib2.HTTPError: HTTP Error 401: Unauthorized.Я не могу понять, есть ли что-то не так с моим ключом, или методом подписания, или я каким-то образом изменяю свои данные после подписания, или какова сделка.У кого-нибудь есть предложения?

Ответы [ 6 ]

7 голосов
/ 08 октября 2011

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

import urllib2
import oauth2 as oauth
import time

OAUTH_CONSUMER_KEY = "blahblahblah"
OAUTH_CONSUMER_SECRET = "blah"

def oauth_request(url, params, method="GET"):
    # Removed trailing commas here - they make a difference.
    params['oauth_version'] = "1.0" #,
    params['oauth_nonce'] = oauth.generate_nonce() #,
    params['oauth_timestamp'] = int(time.time())

    consumer = oauth.Consumer(key=OAUTH_CONSUMER_KEY,
                              secret=OAUTH_CONSUMER_SECRET)
    params['oauth_consumer_key'] = consumer.key
    req = oauth.Request(method=method, url=url, parameters=params)
    req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None)

    return req


if __name__ == "__main__":
    url = "http://yboss.yahooapis.com/ysearch/web"

    req = oauth_request(url, params={"q": "cats dogs"})
    # This one is a bit nasty. Apparently the BOSS API does not like
    # "+" in its URLs so you have to replace "%20" manually.
    # Not sure if the API should be expected to accept either.
    # Not sure why to_url does not just return %20 instead...
    # Also, oauth2.Request seems to store parameters as unicode and forget
    # to encode to utf8 prior to percentage encoding them in its to_url
    # method. However, it's handled correctly for generating signatures.
    # to_url fails when query parameters contain non-ASCII characters. To
    # work around, manually utf8 encode the request parameters.
    req['q'] = req['q'].encode('utf8')
    req_url = req.to_url().replace('+', '%20')
    print req_url
    result = urllib2.urlopen(req_url)
4 голосов
/ 05 августа 2011

Вот фрагмент кода Python, который работает для меня против Yahoo!БОСС:

import httplib2
import oauth2
import time

OAUTH_CONSUMER_KEY = "Blah"
OAUTH_CONSUMER_SECRET = "Blah"

if __name__ == "__main__":
    url = "http://yboss.yahooapis.com/ysearch/web?q=cats%20dogs"
    consumer = oauth2.Consumer(key=OAUTH_CONSUMER_KEY,secret=OAUTH_CONSUMER_SECRET)
    params = {
        'oauth_version': '1.0',
        'oauth_nonce': oauth2.generate_nonce(),
        'oauth_timestamp': int(time.time()),
    }

    oauth_request = oauth2.Request(method='GET', url=url, parameters=params)
    oauth_request.sign_request(oauth2.SignatureMethod_HMAC_SHA1(), consumer, None)
    oauth_header=oauth_request.to_header(realm='yahooapis.com')

    # Get search results
    http = httplib2.Http()
    resp, content = http.request(url, 'GET', headers=oauth_header)
    print resp
    print content

Я использую заголовок аутентификации для отправки подписи OAuth.

1 голос
/ 07 октября 2011

Вот пример кода для доступа к Yahoo! BOSS API v2, использующий python-oauth в качестве oauth liberary.

OAUTH_CONSUMER_KEY    = "<oauth consumer key>"
OAUTH_CONSUMER_SECRET = "<oauth consumer secret>"
URL                   = "http://yboss.yahooapis.com/ysearch/web"

import urllib
import oauth.oauth as oauth

data = {
    "q": "yahoo boss search",
    "start":0,
    "count":2,
    "format":"json"
}
consumer = oauth.OAuthConsumer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET)
signature_method_plaintext = oauth.OAuthSignatureMethod_PLAINTEXT()
signature_method_hmac_sha1 = oauth.OAuthSignatureMethod_HMAC_SHA1()
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=None, http_method='GET', http_url=URL, parameters=data)
oauth_request.sign_request(signature_method_hmac_sha1, consumer, "")
complete_url = oauth_request.to_url()
response = urllib.urlopen(complete_url)
print "REQUEST URL => %s" % complete_url
print ""
print "RESPONSE =>"
print response.read()
1 голос
/ 28 июля 2011

Вот еще одно решение, на этот раз в Python-Land.Он был составлен Томом Де Смедтом, автором набора для веб-майнинга Pattern .

Я свяжусь с автором python-oauth2, чтобы узнать, можно ли его исправить.

OAUTH_CONSUMER_KEY = "blahblahblah"
OAUTH_CONSUMER_SECRET = "blah"

import urllib
import hmac
import time
import random
import base64

try:
     from hashlib import sha1
     from hashlib import md5
except:
     import sha as sha1
     import md5; md5=md5.new

def hmac_sha1(key, text):
     return hmac.new(key, text, sha1).digest()

def oauth_nonce(length=40):
     h = "".join([str(random.randint(0, 9)) for i in range(length)])
     h = md5(str(time.time()) + h).hexdigest()
     return h

def oauth_timestamp():
     return str(int(time.time()))

def oauth_encode(s):
     return urllib.quote(s, "~")

def oauth_signature(url, data={}, method="get", secret="", token=""):
     # Signature base string: http://tools.ietf.org/html/rfc5849#section-3.4.1
     base  = oauth_encode(method.upper()) + "&"
     base += oauth_encode(url.rstrip("?")) + "&"
     base += oauth_encode("&".join(["%s=%s" % (k, v) for k, v in sorted(data.items())]))
     # HMAC-SHA1 signature algorithm: http://tools.ietf.org/html/rfc5849#section-3.4.2
     signature = hmac_sha1(oauth_encode(secret) + "&" + token, base)
     signature = base64.b64encode(signature)
     return signature

q = "cat"
url = "http://yboss.yahooapis.com/ysearch/" + "web" # web | images | news
data = {
     "q": q,
     "start": 0,
     "count": 50, # 35 for images
     "format": "xml",
     "oauth_version": "1.0",
     "oauth_nonce" : oauth_nonce(),
     "oauth_timestamp" : oauth_timestamp(),
     "oauth_consumer_key" : OAUTH_CONSUMER_KEY,
     "oauth_signature_method" : "HMAC-SHA1",
}
data["oauth_signature"] = oauth_signature(url, data, secret=OAUTH_CONSUMER_SECRET)


complete_url = url + "?" + urllib.urlencode(data)
response = urllib.urlopen(complete_url)
print response.read()
1 голос
/ 27 июля 2011

Поэтому я решил отказаться от Python и попробовать Perl, и он просто сработал. Вот минимальный пример кода:

use strict;
use Net::OAuth;
use LWP::UserAgent;

my $CC_KEY = "blahblahblah";
my $CC_SECRET = "blah";

my $url = 'http://yboss.yahooapis.com/ysearch/web';
print make_request($url, {q => "cat dog", format => "xml", count => 5});

sub make_request {
    my ($url, $args) = @_;

    my $request = Net::OAuth->request("request token")
      ->new(
            consumer_key => $CC_KEY,
            consumer_secret => $CC_SECRET,
            request_url => $url,
            request_method => 'GET',
            signature_method => 'HMAC-SHA1',
            timestamp => time,
            nonce => int(rand 10**6),
            callback => 'oob',
            extra_params => $args,
            protocol_version => Net::OAuth::PROTOCOL_VERSION_1_0A,
            );
    $request->sign;

    my $res = LWP::UserAgent->new(env_proxy=>1)->get($request->to_url); 
    return $res->content if $res->is_success;
    die $res->status_line;
}
0 голосов
/ 26 июля 2011

Я вошел в код urllib2.open с помощью отладчика и обнаружил, что ответ имеет следующий заголовок:

WWW-Authenticate: OAuth oauth_problem="version_rejected", realm="yahooapis.com"

Так что я думаю, что у меня какое-то несоответствие версий OAuth.

...