Памятка для backend-разработчика. Активность ученика (мышь, тесты, задания) шлёт browser SDK — здесь только IP-сессии.
POST https://<anomaly-host>/api/lms/session-ip-events Authorization: Bearer <LMS_TO_ANOMALY_API_KEY> Content-Type: application/json
Ключ LMS_TO_ANOMALY_API_KEY выдаёт команда anomaly-service.
GeoIP (страна, регион, город, ASN, ISP) считается на стороне anomaly-service.
| Момент в LMS | eventType |
Зачем |
|---|---|---|
| Успешный логин / создание сессии | session_started |
зафиксировать IP входа |
| Периодический ping (опционально) | session_ping |
актуальный IP с сервера на каждый запрос |
eventType не передать — по умолчанию session_started.
session_ip_event. LMS не должен определять смену IP и
слать отдельное событие.
| Поле | Описание |
|---|---|
studentId |
ID ученика в LMS |
ipAddress |
IPv4 или IPv6 — только с сервера, не с фронта |
| Поле | Описание |
|---|---|
lmsSessionId |
ID сессии LMS — для dedupe и правила multi-region |
occurredAt |
ISO 8601, например 2026-07-10T10:15:00.000Z |
externalEventId |
уникальный ID — идемпотентность (повтор не создаст дубль) |
eventType |
см. таблицу выше |
studentName, role, userAgent,
courseId, courseTitle, groupId,
groupTitle, moduleId, moduleTitle,
teacherId, teacherName.
Контекст курса обычно уже приходит из browser SDK — на backend можно не дублировать.
{
"studentId": "12345",
"ipAddress": "95.24.10.15"
}
{
"studentId": "12345",
"studentName": "Иванов Иван",
"ipAddress": "95.24.10.15",
"lmsSessionId": "lms-session-abc",
"occurredAt": "2026-07-10T10:15:00.000Z",
"eventType": "session_started",
"externalEventId": "login-12345-20260710101500"
}
Если LMS шлёт ping на каждый авторизованный запрос — сервис сам увидит смену IP. Отдельный
eventType для смены IP не нужен.
{
"studentId": "12345",
"ipAddress": "95.24.10.15",
"lmsSessionId": "lms-session-abc",
"occurredAt": "2026-07-10T10:22:00.000Z",
"eventType": "session_ping",
"externalEventId": "ping-lms-session-abc-20260710102200"
}
curl -X POST "https://anomaly.maximumtest.ru/api/lms/session-ip-events" \
-H "Authorization: Bearer <LMS_TO_ANOMALY_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"studentId": "12345",
"ipAddress": "95.24.10.15",
"lmsSessionId": "lms-session-abc",
"eventType": "session_started"
}'
Успешный ответ: { "ok": true }.
X-Forwarded-For (если доверяешь прокси),
иначе remoteAddress.
// псевдокод
function clientIp(req) {
const forwarded = req.headers['x-forwarded-for'];
if (forwarded) {
return forwarded.split(',')[0].trim();
}
return req.socket.remoteAddress;
}
| Код | Причина | Что делать на LMS |
|---|---|---|
401 |
неверный Bearer token | проверить ключ |
400 |
невалидный payload | исправить запрос |
403 |
KB2035_ANOMALY_ENABLED=false |
не слать или глотать ошибку |
LMS_TO_ANOMALY_API_KEY и URL anomaly-serviceeventType: session_startedlmsSessionId на всю сессиюsession_ping на авторизованных запросах — без детекта смены IP на LMSexternalEventId для идемпотентностиmulti-region-login — пример IP-событий в БД.
POST /api/admin/rules/run — правило
multi_region_login_10min ищет разные регионы по
session_ip_event.