使用twitter身份验证标头的身份验证数据错误

时间:2017-05-13 23:19:18

标签: python urllib2 twitter-oauth

我编写了一个使用OAuth的Python程序。我在使用访问令牌(Twitter作为示例)访问服务资源时观察到一个问题。

我能够成功检索到access_token,但如果我尝试在Twitter中使用access_token作为Authorization标题,则它无法正常工作。但是,如果我将其作为普通的url参数传递,那么我会得到所需的结果。

parameters_access_resource = [
        ('oauth_consumer_key', self.consumerKey),
        ('oauth_signature_method', 'HMAC-SHA1'),
        ('oauth_timestamp', self._timestamp),
        ('oauth_nonce', self._nonce),
        ('oauth_version', '1.0'),
        ('oauth_token', self._accessToken),
        ('oauth_signature', self._signature)
        ]

以下方法工作:

urlLink = "https://api.twitter.com/1.1/account/settings.json"
url = "?".join((urlLink, urllib.urlencode(parameters_access_resource)))
reqobj = urllib2.Request(url,data=[])
resp = urllib2.urlopen(reqobj)
print resp.read()

问题:

根据Twitter文档,access_token应作为Authorization标头传递,因此我修改了以下代码

headers = {
    "Accept": "*/*",
    "Connection": "close",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Content-Type" : "application/x-www-form-urlencoded",
    "Host" : "api.twitter.com",
    "Authorization" : self._getAuthorizationHeader(parameters_access_resource)
    }


def _getAuthorizationHeader(self,params):
    params = dict(params)
    sortedParams = {}
    sortedParams = collections.OrderedDict(sorted(params.items()))
    authHeader = (
    '%s="%s"' % (k, v) for k, v in sortedParams.iteritems())
    retval = "OAuth " + ', '.join(authHeader)
    return retval

url = "https://api.twitter.com/1.1/account/settings.json"
reqobj = urllib2.Request(url,data=[],headers=headers)
resp = urllib2.urlopen(reqobj)
print resp.read()

报告了以下错误,我尝试了不同的组合,包括使用requests模块,但我无法找出问题。

{"errors":[{"code":215,"message":"Bad Authentication data."}]}

有人可以指导我如何解决这个问题。

P.S:我知道有很多模块可用于此任务,但我正在编写此代码用于学习目的。

1 个答案:

答案 0 :(得分:0)

找到解决方案,构建标题时出现问题,我percent-encoding标题的值不是Authentication。下面的代码修复了问题

def _getAuthorizationHeader(self,params):
    params = dict(params)
    sortedParams = {}
    sortedParams = collections.OrderedDict(sorted(params.items()))
    authHeader = (
    '%s="%s"' % (k, self._url_encode(v)) for k, v in sortedParams.iteritems())
    retval = "OAuth " + ', '.join(authHeader)
    return retval

def _url_encode(self,s):
    return urllib.quote(str(s),safe='')