Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shopify HMAC参数验证在Python中失败_Python_Shopify_Hmac - Fatal编程技术网

Shopify HMAC参数验证在Python中失败

Shopify HMAC参数验证在Python中失败,python,shopify,hmac,Python,Shopify,Hmac,我在验证来自Shopify的HMAC参数时遇到一些问题。我根据使用的代码返回了不正确的结果 以下是我的注释代码: import urllib import hmac import hashlib qs = "hmac=96d0a58213b6aa5ca5ef6295023a90694cf21655cf301975978a9aa30e2d3e48&locale=en&protocol=https%3A%2F%2F&shop=myshopname.myshopify.com

我在验证来自Shopify的HMAC参数时遇到一些问题。我根据使用的代码返回了不正确的结果

以下是我的注释代码:

import urllib
import hmac
import hashlib

qs = "hmac=96d0a58213b6aa5ca5ef6295023a90694cf21655cf301975978a9aa30e2d3e48&locale=en&protocol=https%3A%2F%2F&shop=myshopname.myshopify.com&timestamp=1520883022"
解析查询字符串

params = urllib.parse.parse_qs(qs)
提取hmac值

value = params['hmac'][0]
根据文档从查询字符串中删除参数

del params['hmac']
del params['signature']
重新组合参数

new_qs = urllib.parse.urlencode(params)
计算摘要

h = hmac.new(SECRET.encode("utf8"), msg=new_qs.encode("utf8"), digestmod=hashlib.sha256)
返回
False

hmac.compare_digest(h.hexdigest(), value)

从表面上看,这最后一步应该是正确的。这里所遵循的每一步都如Shopify文档中的评论所述。

我将发布我自己问题的答案,因为在梳理了Shopify的论坛和其他SO之后,我找不到任何可以明确回答这个问题的内容

最近,Shopify开始在querystring负载中包含
协议
参数。这本身不会是一个问题,除了Shopify在其文档中忽略了一个事实,即在检查签名时,
/
不应使用URL编码。这是完全没有意义的,因为他们自己在提供的查询字符串中对这些字符进行URL编码

因此,要解决这个问题,只需为
urllib.parse.urlencode
提供
safe
参数,其值为
:/
(fitting,对吗?)。完整的工作代码如下所示:

params = urllib.parse.parse_qsl(qs)
cleaned_params = []
hmac_value = dict(params)['hmac']

# Sort parameters
for (k, v) in sorted(params):
    if k in ['hmac', 'signature']:
        continue

    cleaned_params.append((k, v))

new_qs = urllib.parse.urlencode(cleaned_params, safe=":/")
secret = SECRET.encode("utf8")
h = hmac.new(secret, msg=new_qs.encode("utf8"), digestmod=hashlib.sha256)

# Compare digests
hmac.compare_digest(h.hexdigest(), hmac_value)
希望这对其他遇到这个问题的人有所帮助


请注意,由于查询参数不是按字典(字母顺序)排序的,因此此代码有点简化。如果可以更清楚地说明这一点,我也可以更新代码来做到这一点。

@deliriousoops,那将是一个打字错误。抱歉,我的荣幸,@SamCreamer!可能太晚了,但有人知道“秘密”在哪里(和什么)?我尝试使用“API密钥”,但没有验证(返回False).@lowercase00应该是它;至少这是我的代码库中的内容。@DanLoewenherz最后一行代码中的“值”应该是“hmac_值”@vantrong291感谢您捕捉到这一点,刚刚更新
import hmac
import hashlib


...

# Inside your view in Django's views.py
params = request.GET.dict()
#

myhmac = params.pop('hmac')
params['state'] = int(params['state'])
line = '&'.join([
    '%s=%s' % (key, value)
    for key, value in sorted(params.items())
])
print(line)
h = hmac.new(
    key=SHARED_SECRET.encode('utf-8'),
    msg=line.encode('utf-8'),
    digestmod=hashlib.sha256
)

# Cinderella ?
print(hmac.compare_digest(h.hexdigest(), myhmac))