Кабинет клиента: документы и корпоративные действия, дистрибутив, обратный канал, защита
Данные - корпоративные действия по бумагам клиента (U_CA_ACTS), готовые выписки (U_OP_INF_EXTRACT), заявки клиента на документ (lk.doc_requests) с оповещением сотрудникам; страница «Документы» - дистрибутив кабинета из настроек ядра: архив с программой, службой, настройками, установщиком и инструкцией; ключ доступа на странице показан замаскированным Связь без публичного адреса у ядра - режим ожидания (BJ_MODE=agent): кабинет копит запросы, ядро само подключается к нему, выполняет их обработчиком /api/lk/* и возвращает ответы; 4 параллельных подключения, тот же ключ модуля в обе стороны, состояние канала в настройках - сквозной тест: настоящий кабинет + настоящий цикл ядра Защита (по итогам аудита) - вход: лимит попыток по адресу и логину, одинаковое время ответа для несуществующего логина, пароль от 10 символов - сессии ядра: на диске отпечаток токена и ссылка на учётную запись, без персональных данных; карточка клиента читается из БД на каждый запрос (блокировка действует сразу); абсолютный срок 24 ч; привязка к браузеру, к сети — по настройке - вход сотрудника в кабинет клиента пишется в lk.audit и поднимает оповещение - кабинет: CSRF на всех формах, /impersonate только POST, куки HttpOnly+Secure+SameSite=Strict, выход гасит все сессии, заголовки CSP/X-Frame-Options/nosniff/HSTS, no-store, таймауты сервера, ограничение тела, recover; сообщения через куку вместо адреса; /health наружу без подробностей - шрифты вшиты в программу: страница не обращается к сторонним сайтам - экранирование LIKE в выборках по номеру договора; ключ и токен без суррогата при отказе rand - исправлено: ошибка входа не показывалась клиенту (шаблон ждал Error, приходил Flash) Тесты: lksecurity_test, lkagent_test, lkdist_test, modules/lk (CSRF, заголовки, режим ожидания), живые lkcoverage/lkunpriced, scripts/lk-sec-smoke.sh — проверка работающего кабинета снаружи. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -48,7 +48,7 @@ func depoContractExists(ctx context.Context, s FancyMSSQLSettings, contract stri
|
||||
var full string
|
||||
err = conn.QueryRowContext(cctx,
|
||||
"SELECT TOP 1 PORT_NUM FROM OD_CLIENTS_PORTS WHERE PORT_NUM=@p1 OR PORT_NUM LIKE @p2",
|
||||
contract, contract+" %").Scan(&full)
|
||||
contract, likeEscape(contract)+" %").Scan(&full)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func depoClientPositions(ctx context.Context, s FancyMSSQLSettings, contract str
|
||||
WHERE (p.PORT_NUM = @p1 OR p.PORT_NUM LIKE @p2)
|
||||
AND CAST(rst.K AS float) <> 0
|
||||
ORDER BY v.NAME`
|
||||
rows, err := conn.QueryContext(cctx, q, contract, contract+" %")
|
||||
rows, err := conn.QueryContext(cctx, q, contract, likeEscape(contract)+" %")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -218,3 +218,11 @@ func depoFindContracts(ctx context.Context, s FancyMSSQLSettings, like string, l
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// likeEscape — экранирование шаблона LIKE. Номер договора приходит от клиента, и
|
||||
// знаки % _ [ в нём должны означать сами себя, а не подстановку: иначе договор
|
||||
// вида «БР-1%» совпал бы с чужими счетами.
|
||||
func likeEscape(v string) string {
|
||||
r := strings.NewReplacer("[", "[[]", "%", "[%]", "_", "[_]")
|
||||
return r.Replace(v)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user