【问题标题】:Yahoo BOSS V2 authorization troubles雅虎 BOSS V2 授权问题
【发布时间】:2011-10-11 10:08:10
【问题描述】:

我在 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 异常。我无法弄清楚我的密钥或签名方法是否有问题,或者我是否在签名后以某种方式篡改了我的数据,或者交易是什么。有人有建议吗?

【问题讨论】:

    标签: python oauth yahoo


    【解决方案1】:

    我做了一些小改动以使您的示例正常工作。请参阅 cmets 的代码。

    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)
    

    【讨论】:

    • 谢谢 OG Dude,您的解决方案奏效了。非常感谢
    【解决方案2】:

    这是访问 Yahoo! 的示例代码BOSS API v2 使用 python-oauth 作为 oauth 库。

    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()
    

    【讨论】:

    • 谢谢 - 很遗憾,我实际上无法验证这是否有效,因为我已不在该公司,并且无法访问他们的 OAUTH 密钥。
    • 嗨,Ken,感谢您提出问题和解决方案。这对我帮助很大。如果您仍然对 Y! BOSS,您可以在developer.apps.yahoo.com/dashboard/createKey.html获取自己的密钥。
    【解决方案3】:

    这是一个 Python 代码 sn-p,它适用于我对抗 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
    

    我正在使用 Authenticate Header 来提交 OAuth 签名。

    【讨论】:

    • 通过将urllib 排除在循环之外,不幸的是,这不会使用urllib 的代理检测机制。我无法让 httplib2 的代理设置与我的防火墙一起使用。
    • 它给了我错误raise IncompleteRead(''.join(value)) httplib.IncompleteRead: IncompleteRead(6303 bytes read)
    【解决方案4】:

    这是另一个解决方案,这次是在 python-land 中。这是 Pattern 网络挖掘工具包的作者 Tom De Smedt 整理的。

    我会和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()
    

    【讨论】:

    • 我似乎无法让它适用于包含空格的查询。例如,尝试 q = "cats" 任何建议将不胜感激。
    • kv 中的任何一个包含需要百分比编码的字符时,base += oauth_encode("&amp;".join(["%s=%s" % (k, v) for k, v in sorted(data.items())])) 不会产生签名基本字符串的有效部分。如果根据规范我没有弄错,您将不得不: 1. 将 data 中的所有键/值编码为 utf8 2. 将其有序编码的键/值对连接成查询字符串 k1=v1&amp;k2=kv... 3. 对结果进行百分比编码细绳。原帖中的oauth2 模块实际上是正确的——问题是另一个问题。
    【解决方案5】:

    所以我决定放弃 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;
    }
    

    【讨论】:

      【解决方案6】:

      使用调试器进入urllib2.open代码,发现响应中有这个header:

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

      所以我猜我的 OAuth 版本不匹配。

      【讨论】:

      • 我认为这是一个红鲱鱼。摆弄oauth_version 参数并没有改善问题;此外,Y-BOSS 文档说要使用1.0,所以我不知道那个错误应该是什么意思。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-26
      相关资源
      最近更新 更多