在Pyramid oauth提供者中生成请求令牌时出现无效签名错误

1 投票
1 回答
4685 浏览
提问于 2025-04-16 21:13

我正在尝试在一个Pyramid应用中使用oauth2生成请求令牌,以控制我正在开发的API的访问权限。现在我卡在了验证我的消费者密钥和秘密上,参考了这个例子。在Pyramid的请求令牌端点,我有以下内容:

@view_config(route_name = "api_request_token", request_method = "GET")
def api_request_token(request):
    auth_header = {}
    if ('Authorization' in request.headers):
        auth_header = {'Authorization': request.headers['Authorization']}

    req = oauth2.Request.from_request(
        request.method,
        request.url,
        headers = auth_header,
        query_string = request.query_string)

    try:
        oauth_server.verify_request(req, ConsumerKeySecret.getByConsumerKey(request.params.get('oauth_consumer_key')), None)
    except oauth2.Error, e:
        print e
    except KeyError, e:
        print e
    except Exception, e:
        print e

(ConsumerKeySecret.getByConsumerKey是一个SQLAlchemy模型的类方法,它为给定的key设置了实例变量keysecret。)

在消费者端,我又按照之前提到的博客文章做了以下操作:

def build_request(url, method='GET'):
    params = {                                            
        'oauth_version': "1.0",
        'oauth_nonce': oauth2.generate_nonce(),
        'oauth_timestamp': int(time.time()),
        'oauth_signature_method': 'HMAC-SHA1',
    }
    consumer = oauth2.Consumer(key='b9085cb942dc427c92dd', secret='1735fd5b090381dcaf57')
    params['oauth_consumer_key'] = consumer.key
    req = oauth2.Request(method=method, url=url, parameters=params)
    signature_method = oauth2.SignatureMethod_HMAC_SHA1()
    req.sign_request(signature_method, consumer, None)
    return req

request = build_request("http://localhost:6543/api/01/request_token")
u = urllib2.urlopen(request.to_url())

然而,验证失败了,出现了以下错误:

无效的签名。预期的签名基础字符串:GET&http%3A%2F%2Flocalhost%3A6543%2Fapi%2F01%2Frequest_token&oauth_body_hash%3D2jmj7l5rSw0yVb%252FvlWAYkK%252FYBwk%253D%26oauth_body_hash%3D2jmj7l5rSw0yVb%252FvlWAYkK%252FYBwk%253D%26oauth_consumer_key%3Db9085cb942dc427c92dd%26oauth_consumer_key%3Db9085cb942dc427c92dd%26oauth_nonce%3D42023151%26oauth_nonce%3D42023151%26oauth_signature_method%3DHMAC-SHA1%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1310338562%26oauth_timestamp%3D1310338562%26oauth_version%3D1.0%26oauth_version%3D1.0

我有点困惑,因为每个查询字符串参数在“预期”的签名中似乎出现了两次。可能出什么问题了呢?

如果这个问题容易回答,我还有一个后续问题:一旦我验证了请求,如何生成请求令牌?oauth2库在这方面的文档有点模糊,而且大多数示例似乎都是针对实现消费者的,而不是创建提供者。

谢谢!

更新 我在回答自己的问题,给出我认为的答案。从这个bug报告来看,oauth_body_hash参数的包含搞乱了我的签名验证,因为我使用的是GET。把它改成POST解决了这个问题。奇怪的是,考虑到我也在用这个库进行测试,居然会发生这种情况。

至于第二部分,我相信你可以生成任何随机且足够长的密钥/秘密对。我见过有人把某个随机源的sha1哈希分成两个20个字符的部分。然后你可以使用oauth2.Token自动创建一个URL,然后在你的authorize_token步骤中使用。

当然,如果我在这些方面有错,请一定告诉我。

1 个回答

1

这听起来就像我遇到的问题,不过我找到了一种不同的(可能的)解决办法。

看起来所有的查询字符串参数都被包含了两次,这在这个错误报告中有描述:https://github.com/simplegeo/python-oauth2/issues/21

按照报告中提到的方法去掉查询字符串参数后,我的问题就解决了。

撰写回答