我正在按照这个page的说明进行操作。我正在构建一个松弛的斜杠命令处理服务器,并且我无法重新构建签名来验证斜杠请求的真实性。
下面是我的django应用程序的代码片段(视图使用django rest-framework APIView):
@property
def x_slack_req_ts(self):
if self.xsrts is not None:
return self.xsrts
self.xsrts = str(self.request.META['HTTP_X_SLACK_REQUEST_TIMESTAMP'])
return self.xsrts
@property
def x_slack_signature(self):
if self.xss is not None:
return self.xss
self.xss = self.request.META['HTTP_X_SLACK_SIGNATURE']
return self.xss
@property
def base_message(self):
if self.bs is not None:
return self.bs
self.bs = ':'.join(["v0", self.x_slack_req_ts, self.raw.decode('utf-8')])
return self.bs
@property
def encoded_secret(self):
return self.app.signing_secret.encode('utf-8')
@property
def signed(self):
if self.non_base is not None:
return self.non_base
hashed = hmac.new(self.encoded_secret, self.base_message.encode('utf-8'), hashlib.sha256)
self.non_base = "v0=" + hashed.hexdigest()
return self.non_base这是在一个类中,其中self.raw = request.body是django请求,而self.app.signing_secret是一个带有适当松弛秘密字符串的字符串。当self.non_base产生不准确的值时,它不起作用。
现在,如果我打开一个交互式python repl并执行以下操作:
>>> import hmac
>>> import hashlib
>>> secret = "8f742231b10e8888abcd99yyyzzz85a5"
>>> ts = "1531420618"
>>> msg = "token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c"
>>> ref_signature = "v0=a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503"
>>> base = ":".join(["v0", ts, msg])
>>> hashed = hmac.new(secret.encode(), base.encode(), hashlib.sha256)
>>> hashed.hexdigest()
>>> 'a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503'您将会识别出引用的链接示例。如果我在示例中使用django应用程序中的值,它可以在repl中工作,但不能在django应用程序中工作。
我的问题是:我认为这是由于self.raw.decode()编码与我提取来复制/粘贴到repl中的打印输出不一致造成的。有没有人遇到过这个问题?解决方法是什么?我用urllib.parse库尝试了一些随机的东西……如何确保request.body编码与使用get_data()的flask中的示例一致(如链接中的文档所建议的)?
更新:我定义了一个自定义解析器:
class SlashParser(BaseParser):
"""
Parser for form data.
"""
media_type = 'application/x-www-form-urlencoded'
def parse(self, stream, media_type=None, parser_context=None):
"""
Parses the incoming bytestream as a URL encoded form,
and returns the resulting QueryDict.
"""
parser_context = parser_context or {}
request = parser_context.get('request')
raw_data = stream.read()
data = QueryDict(raw_data, encoding='utf-8')
setattr(data, 'raw_body', raw_data) # setting a 'body' alike custom attr with raw POST content
return data为了在自定义解析器中基于this question和raw_body进行测试,生成与正常“正文”完全相同的散列签名,但同样,将粘贴复制到repl中以在DRF外部进行测试。我很确定这是一个编码问题,但完全不知所措...
发布于 2019-02-15 03:49:23
我发现这个问题非常令人沮丧。
事实证明,签名密钥存储在太短的字符串数组中,并且缺少尾随字符,这显然会导致消息的散列错误。
https://stackoverflow.com/questions/54681902
复制相似问题