【发布时间】:2019-03-28 08:06:02
【问题描述】:
我在 Slack 的 Flask 应用程序中收到一个 POST 请求。当用户按下交互式消息按钮时发送请求。根据 Slack docs 我必须提取请求的正文以验证签名。 不过,我计算的签名与 Slack 发送的签名不匹配。 事实上,请求的主体是一些编码字符串。正如预期的那样,该字符串实际上是一个编码字典而不是查询 str 参数。
这是我观点的开始:
@app.route('/register', methods=['POST'])
def register_visit():
data = request.get_data()
signature = request.headers.get('X-Slack-Signature', None)
timestamp = request.headers.get('X-Slack-Request-Timestamp', None)
signing_secret = b'aaaaaaaaaaaaaaaa'
# old message, ignore
if round(actual_time.time() - float(timestamp)) > 60 * 5:
return
concatenated = ("v0:%s:%s" % (timestamp, data)).encode('utf-8')
computed_signature = 'v0=' + hmac.new(signing_secret, msg=concatenated, digestmod=hashlib.sha256).hexdigest()
if hmac.compare_digest(computed_signature, signature):
...
我尝试格式化接收到的数据,使其看起来像:
token=fdjkgjl&user_id=1234... 但我不知道数据中必须存在的所有必要参数。
高度赞赏任何想法。
邮件正文如下 - 在 URL 解码后(注意我修改了可能的敏感数据):
b'payload={"type":"interactive_message","actions": [{"name":"yes_button","type":"button","value":"236"}],"callback_id":"visit_button","team":{"id":"fffff"," domain":"ffff"},"channel":{"id":"ffff","name":"directmessage"},"user":{"id":"ffffff","name":"fffft" },"action_ts":"1540403943.419120","message_ts":"1541403949.000100","attachment_id":"1","token":"8LpjBuv13J7xAjhl2lEajoBU","is_app_unfurl":false,"original_message":{"text":"测试","bot_id":"DDDDDDDDDD","attachments":[{"callback_id":"visit_button","text":"Register","id":1,"color":"3AA3E3","actions" :[{"id":"1","name":"yes_button","text":"Yes","type":"button","value":"236","style":""} ],"fallback":"Register"}],"type":"message","subtype":"bot_message","ts":"1540413949.000100"},"response_url":"https://hooks.slack. com/actions/ffffff/ffffff/tXJjx1XInaUhrikj6oEzK08e","trigger_id":"464662548327.425084163429.dda35a299eedb940ab98dbb9386b56f0"}'
【问题讨论】:
-
看看官方的python slack API客户端:github.com/slackapi/python-slackclient。
-
在我看来,您混淆了请求的标头和正文。标头将包含签名,正文将包含请求中的所有其他内容(例如用户 ID)。请注意,正文是具有单个属性
payload的 POST 表单。该属性包含 JSON 数组形式的请求数据。见here -
@ErikKalkoken 您到底在哪里看到我让他们感到困惑?正文确实包含有效负载。这正是我得到的。但是检查一下,正文是这样的:b'payload=%7B%22type%22%3A%22interactive_message%22%2C%22actions%22%3A%5B%7B%22name%22%3A%22kaynti。 ..'
-
@Fian 好吧,我想要实现的功能不需要任何库。这只是一个常规的 POST 请求,我应该能够使用 Python/Flask 内置功能来处理它。您是否使用该库来处理交互式消息?
-
也许我当时理解错了。道歉。你的身体是 URL 编码的。我对 Python / Flask 不是很熟悉,但您应该使用
request.form.get('payload')以纯文本形式获取它。 Source