我正在尝试使用网站的OAuth,这要求签名方法仅为“HMAC-SHA1”。
我想知道如何在Python中实现它?
答案 0 :(得分:71)
Pseudocodish:
def sign_request():
from hashlib import sha1
import hmac
# key = b"CONSUMER_SECRET&" #If you dont have a token yet
key = b"CONSUMER_SECRET&TOKEN_SECRET"
# The Base String as specified here:
raw = b"BASE_STRING" # as specified by OAuth
hashed = hmac.new(key, raw, sha1)
# The signature
return hashed.digest().encode("base64").rstrip('\n')
签名错误通常存在于基本字符串中,请确保您理解这一点(如OAuth1.0规范所述:http://tools.ietf.org/html/draft-hammer-oauth-10#section-3.4.1)。
以下输入用于生成签名基本字符串:
参数,按字母顺序排列,例如(换行符的换行符):
file=vacation.jpg
&oauth_consumer_key=dpf43f3p2l4k3l03
&oauth_nonce=kllo9940pd9333jh
&oauth_signature_method=HMAC-SHA1
&oauth_timestamp=1191242096
&oauth_token=nnch734d00sl2jdk
&oauth_version=1.0
&size=original
对每个部分进行连接和URL编码,结果如下:
GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26
oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26
oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26
oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal
答案 1 :(得分:12)
为了爱上帝,如果你对oauth做任何事情,请使用requests
库来获取Python!我尝试使用Python中的hmac
库实现HMAC-SHA1,并且很多麻烦,尝试创建正确的oauth基本字符串等。只需使用请求即可:
>>> import requests
>>> from requests_oauthlib import OAuth1
>>> url = 'https://api.twitter.com/1.1/account/verify_credentials.json'
>>> auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET', 'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')
>>> requests.get(url, auth=auth)
答案 2 :(得分:7)
答案 3 :(得分:3)
最后,这是一个使用oauthlib的实际工作解决方案(使用Python 3测试)。
我使用官方RTF 1中的第一个OAuth步骤作为示例:
Client Identifier: dpf43f3p2l4k3l03
Client Shared-Secret: kd94hf93k423kf44
POST /initiate HTTP/1.1
Host: photos.example.net
Authorization: OAuth realm="Photos",
oauth_consumer_key="dpf43f3p2l4k3l03",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="137131200",
oauth_nonce="wIjqoS",
oauth_callback="http%3A%2F%2Fprinter.example.com%2Fready",
oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D"
我们想要计算oauth_signature
的值。
以下定义了我们要签名的内容:
# There is no query string present.
# In case of http://example.org/api?a=1&b=2 - the value
# would be "a=1&b=2".
uri_query=""
# The oauthlib function 'collect_parameters' automatically
# ignores irrelevant header items like 'Content-Type' or
# 'oauth_signature' in the 'Authorization' section.
headers={
"Authorization": (
'OAuth realm="Photos", '
'oauth_nonce="wIjqoS", '
'oauth_timestamp="137131200", '
'oauth_consumer_key="dpf43f3p2l4k3l03", '
'oauth_signature_method="HMAC-SHA1", '
'oauth_callback="http://printer.example.com/ready"'
)
}
# There's no POST data here - in case it was: x=1 and y=2,
# then the value would be '[("x","1"),("y","2")]'.
data=[]
# This is the above specified client secret which we need
# for calculating the signature.
client_secret="kd94hf93k423kf44"
我们走了:
import oauthlib.oauth1.rfc5849.signature as oauth
params = oauth.collect_parameters(
uri_query="",
body=data,
headers=headers,
exclude_oauth_signature=True,
with_realm=False
)
norm_params = oauth.normalize_parameters(params)
base_string = oauth.construct_base_string(
"POST",
"https://photos.example.net/initiate",
norm_params
)
sig = oauth.sign_hmac_sha1(
base_string,
client_secret,
'' # resource_owner_secret - not used
)
from urllib.parse import quote_plus
print(sig)
# 74KNZJeDHnMBp0EMJ9ZHt/XKycU=
print(quote_plus(sig))
# 74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D
答案 4 :(得分:1)
the oauth website有多个python库可供使用,但如果您只是对特定实现感兴趣,可以查看one of them。
答案 5 :(得分:1)
您可以尝试以下方法。
def _hmac_sha1(input_str):
raw = input_str.encode("utf-8")
key = 'your_key'.encode('utf-8')
hashed = hmac.new(key, raw, hashlib.sha1)
return base64.encodebytes(hashed.digest()).decode('utf-8')
答案 6 :(得分:0)
在Python 3.7中,有一种优化的方法可以做到这一点。 HMAC(key,msg,摘要).digest()使用优化的C或内联实现,对于适合内存的消息,此方法更快。
为给定的密钥和摘要返回味精的摘要。该功能是 等效于HMAC(key,msg,摘要).digest(),但使用优化的C 或内联实现,对于适合 记忆。参数key,味精和摘要的含义与 在new()中。
CPython实现细节,仅优化的C实现 当摘要是摘要算法的字符串和名称时使用,即 由OpenSSL支持。
答案 7 :(得分:0)
在Python 3.7中,有一种优化的方法可以做到这一点。 HMAC(key,msg,摘要).digest()使用优化的C或内联实现,对于适合内存的消息,此方法更快。