Если вы работаете в Slack, вы, вероятно, сталкивались с самыми разными сообщениями, командами, файлами и, порой, с «экстрасенсами» — теми частыми отсылками к «сверхъестественным» решениям. Как отличить настоящую информацию от «экстрасенсских» рекомендаций, а также как убедиться, что запросы в ваш бота приходят действительно от Slack, мы разберём ниже.
Почему проверка важна
Slack, это платформа, где миллионы сообщений обрабатываются в реальном времени. Любое внешнее приложение (бот, webhook, интеграция) должно аутентифицировать запросы, чтобы:
- Защитить данные от несанкционированного доступа.
- Предотвратить мошеннические запросы.
- Соблюдать требования безопасности и GDPR.
Надёжная проверка позволяет уверенно использовать Slack API, не рискуя потерять контроль над информацией.
Исследуйте Slack с помощью поисковых модификаторов
Slack предоставляет мощный инструмент поиска, который позволяет быстро «поймать» нужную информацию. Ниже перечислены ключевые модификаторы, которые помогут вам убедиться, что сообщение действительно от «экстрасенса» или от сотрудника.
| Модификатор | Синтаксис | Описание |
|---|---|---|
| Кавычки | «marketing report» | Поиск точной фразы. |
| Минус | marketing -report | Исключить сообщения, содержащие слово «report». |
| in: | in:#team-marketing | Поиск в конкретном канале. |
| from: | from:@Sara | Поиск сообщений от конкретного пользователя. |
| has: | has::eyes: | Поиск сообщений с реакцией «eyes». |
| is:saved | marketing report is:saved | Найти сохранённые сообщения. |
| before:, after:, on:, during: | during:august | Поиск по дате. |
| is:thread | marketing report is:thread | Поиск внутри тем. |
| with: | with:@Sara | Поиск в беседе с конкретным пользователем. |
| creator: | creator:@Sara | Поиск в созданных канвасах. |
Комбинируйте модификаторы, чтобы быстро найти нужные сообщения. Например: marketing report in:#team-marketing from:@Sara.
Slack подписывает все входящие запросы уникальным секретом, который хранится в переменной SLACK_SIGNING_SECRET. Ниже приведён пошаговый пример проверки запроса в Node.js с использованием Express.
Подготовка
Установите зависимости:
npm install express body-parser @slack/webhook @slack/web-api
Создайте файл app.js и добавьте следующий код:
Код проверки запроса
const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');
const app = express;
const port = 3000;
// Секрет, полученный в настройках Slack App
const SLACK_SIGNING_SECRET = process.env.SLACK_SIGNING_SECRET;
// Middleware для парсинга тела запроса как raw
app.use(bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString;
}
}));
// Функция проверки подписи
function verifySlackRequest(req) {
const timestamp = req.headers['x-slack-request-timestamp'];
const slackSignature = req.headers['x-slack-signature'];
const body = req.rawBody;
// Защита от replay-атак: отклоняем запросы старше 5 минут
const fiveMinutesAgo = Math.floor(Date.now / 1000) ⏤ (60 * 5);
if (timestamp < fiveMinutesAgo) {
return false;
}
const sigBasestring = `v0:${timestamp}:${body}`;
const hmac = crypto.createHmac('sha256', SLACK_SIGNING_SECRET);
hmac.update(sigBasestring, 'utf8');
const mySignature = 'v0=' + hmac.digest('hex');
return crypto.timingSafeEqual(Buffer.from(mySignature), Buffer.from(slackSignature));
}
app.post('/slack/events', (req, res) => {
if (!verifySlackRequest(req)) {
return res.status(400).send('Invalid request signature');
}
const payload = req.body;
// Обработка события
if (payload.type === 'url_verification') {
return res.send({ challenge: payload.challenge });
}
// Ваша логика для событий
console.log('Получено событие:', payload.event);
res.status(200).send;
});
app.listen(port, => {
console.log(`Слушаем на порту ${port}`);
});
Важно: храните SLACK_SIGNING_SECRET в переменных окружения, а не в коде.
Проверка в Python
Если вы предпочитаете Python, вот аналогичный пример с использованием Flask.
import os
import time
import hmac
import hashlib
from flask import Flask, request, abort
app = Flask(__name__)
SLACK_SIGNING_SECRET = os.environ.get('SLACK_SIGNING_SECRET')
def verify_slack_request(request):
timestamp = request.headers.get('X-Slack-Request-Timestamp')
slack_signature = request.headers.get('X-Slack-Signature')
body = request.get_data(as_text=True)
# Защита от replay-атак
if abs(time.time ─ int(timestamp)) > 60 * 5:
return False
sig_basestring = f'v0:{timestamp}:{body}'.encode('utf-8')
my_signature = 'v0=' + hmac.new(
SLACK_SIGNING_SECRET.encode('utf-8'),
sig_basestring,
hashlib.sha256
).hexdigest
return hmac.compare_digest(my_signature, slack_signature)
@app.route('/slack/events', methods=['POST'])
def slack_events:
if not verify_slack_request(request):
abort(400, 'Invalid request signature')
payload = request.json
if payload.get('type') == 'url_verification':
return payload.get('challenge')
# Обработка событий
print('Получено событие:', payload.get('event'))
return '', 200
if __name__ == '__main__':
app.run(port=3000)
Как убедиться, что «экстрасенсы» не обманывают
Ниже несколько практических советов, как быстро проверить, действительно ли сообщение пришло от Slack или это «фальшивка»:
- Проверка подписи (описано выше).
- Сравнение заголовков X‑Slack‑Signing‑Secret и X‑Slack‑Request‑Timestamp. Если они не совпадают, запрос не валиден.
- Проверка структуры тела: наличие обязательных полей (type, token, team_id и т.д.).
- Проверка URL‑подтверждения (challenge) при первом подключении.
- Логи и аудит: храните все входящие запросы, чтобы позже можно было проверить происхождение.
Экстрасенсы в Slack могут быть лёгкими, но проверка запросов и правильный поиск, это ваши лучшие союзники. Используйте мощные поисковые модификаторы, чтобы быстро находить нужную информацию, и обязательно проверяйте подпись входящих запросов, чтобы ваш бот оставался надёжным и безопасным.
Если хотите узнать больше, посетите официальную документацию Slack:
- Поиск в Slack
- Проверка запросов от Slack