Flask搭建Slack Bot生产环境遇请求验证失败问题求助
问题
我正在开发首个基于Flask的Slack Bot,用来响应频道消息,步骤包括:
- 创建Slack应用,配置事件订阅(提及、消息等)并获取密钥
- 用ngrok将本地Flask应用映射到公网,完成事件订阅
- 编写Bot逻辑并集成到Flask应用
本地用ngrok运行正常,但部署到生产服务器后,URL验证失败,提示Your URL didn't respond with the value of the challenge parameter。我专门写了返回challenge参数的方法,简化逻辑后还是报错slackeventsapi.server.SlackEventAdapterException: Invalid request timestamp。
我的代码:
import os from flask import Flask, request from slackeventsapi import SlackEventAdapter app = Flask(__name__) slack_bot_user_id = os.getenv('SLACK_BOT_USER_ID') slack_events_adapter = SlackEventAdapter(os.getenv('SLACK_SIGNING_SECRET'), '/slack/events', app) @app.route('/slack/events', methods=['POST']) def get_events(): # print(request) return request.json['challenge'] @slack_events_adapter.on('message') def handle_message(event_data): print(event_data) if __name__ == '__main__': app.run(port=8000, host='0.0.0.0')
我理解的逻辑:
- 第6行用适配器连接Flask和Slack应用
- 第9-13行定义返回Events API要求的challenge参数的函数
- 第15-17行是逻辑占位符,等验证通过后再补充
用curl测试:
curl -X POST -d '{"challenge": "empty"}' -H "Content-Type: application/json" 127.0.0.1:8000/slack/events
结果没进入get_events函数,直接报错:
Traceback (most recent call last): File "/Users/rsuleimanov/Documents/llm_deeds/langchainenv/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app response = self.full_dispatch_request() File "/Users/rsuleimanov/Documents/llm_deeds/langchainenv/lib/python3.9/site-packages/flask/app.py", line 1486, in full_dispatch_request rv = self.handle_user_exception(e) File "/Users/rsuleimanov/Documents/llm_deeds/langchainenv/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request rv = self.dispatch_request() File "/Users/rsuleimanov/Documents/llm_deeds/langchainenv/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) File "/Users/rsuleimanov/Documents/llm_deeds/langchainenv/lib/python3.9/site-packages/slackeventsapi/server.py", line 94, in event self.emitter.emit('error', slack_exception) File "/Users/rsuleimanov/Documents/llm_deeds/langchainenv/lib/python3.9/site-packages/pyee/base.py", line 211, in emit self._emit_handle_potential_error(event, args[0] if args else None) File "/Users/rsuleimanov/Documents/llm_deeds/langchainenv/lib/python3.9/site-packages/pyee/base.py", line 169, in _emit_handle_potential_error raise error slackeventsapi.server.SlackEventAdapterException: Invalid request timestamp
加请求头-H "X-Slack-Request-Timestamp: 1717762997"测试,又出现Invalid request signature错误。请问怎么正确通过Slack事件验证?
解决方案
1. 移除重复路由,让适配器自动处理验证
你同时用SlackEventAdapter注册了/slack/events路由,又自定义了同名路由,导致适配器的验证逻辑优先触发,你的自定义路由根本无法执行。直接删除自己写的get_events函数,SlackEventAdapter会自动处理challenge验证流程。
修改后的代码:
import os from flask import Flask, request from slackeventsapi import SlackEventAdapter app = Flask(__name__) slack_bot_user_id = os.getenv('SLACK_BOT_USER_ID') # 适配器自动处理/slack/events路由,包含challenge验证 slack_events_adapter = SlackEventAdapter(os.getenv('SLACK_SIGNING_SECRET'), '/slack/events', app) @slack_events_adapter.on('message') def handle_message(event_data): print(event_data) if __name__ == '__main__': app.run(port=8000, host='0.0.0.0')
2. 同步生产服务器时间
Slack的签名验证依赖请求时间戳,如果服务器时间与Slack服务器时间差超过5分钟,就会触发Invalid request timestamp错误。检查生产服务器的系统时间,确保开启NTP时间同步服务。
3. 确认签名密钥与环境变量正确性
- 确保生产服务器上的
SLACK_SIGNING_SECRET环境变量值,与Slack应用后台的Signing Secret完全一致,无多余空格或拼写错误。 - 本地测试时不要手动添加
X-Slack-Request-Timestamp头,Slack会自动生成合法的时间戳和签名,手动添加的头会导致签名验证失败。
4. 生产部署配置检查
如果用Gunicorn、UWSGI等WSGI服务器部署Flask应用,确保绑定0.0.0.0和正确端口,同时服务器防火墙允许Slack的IP访问该端口。
内容的提问来源于stack exchange,提问作者Rail Suleymanov

