Попереименовывал классы и запросы для авторификации.
Вроде хоршо и наверное всё работает :) пока не тестил
This commit is contained in:
AidarKC 2025-12-10 12:58:16 +03:00
parent 888bb1595f
commit 47c53c1a14
17 changed files with 383 additions and 88 deletions

View File

@ -1,15 +1,15 @@
package server.logic.ws_protocol.JSON; package server.logic.ws_protocol.JSON;
import server.logic.ws_protocol.JSON.entyties.*; import server.logic.ws_protocol.JSON.entyties.*;
import server.logic.ws_protocol.JSON.entyties.Auth.NetAuthSessionNewStep1Request; import server.logic.ws_protocol.JSON.entyties.Auth.Net_AuthChallenge_Request;
import server.logic.ws_protocol.JSON.entyties.Auth.NetAuthSessionNewStep2Request; import server.logic.ws_protocol.JSON.entyties.Auth.Net_CreateAuthSession_Request;
import server.logic.ws_protocol.JSON.entyties.Auth.NetSessionRefreshRequest; import server.logic.ws_protocol.JSON.entyties.Auth.Net_RefreshSession_Request;
import server.logic.ws_protocol.JSON.handlers.*; import server.logic.ws_protocol.JSON.handlers.*;
import server.logic.ws_protocol.JSON.entyties.tempToTest.NetAddUserRequest; import server.logic.ws_protocol.JSON.entyties.tempToTest.NetAddUserRequest;
import server.logic.ws_protocol.JSON.handlers.auth.NetAuthSessionNewStep2Handler; import server.logic.ws_protocol.JSON.handlers.auth.Net_CreateAuthSession__Handler;
import server.logic.ws_protocol.JSON.handlers.auth.Net_RefreshSession_Handler;
import server.logic.ws_protocol.JSON.handlers.tempToTest.NetAddUserHandler; import server.logic.ws_protocol.JSON.handlers.tempToTest.NetAddUserHandler;
import server.logic.ws_protocol.JSON.handlers.auth.NetAuthSessionNewStep1Handler; import server.logic.ws_protocol.JSON.handlers.auth.Net_AuthChallenge_Handler;
import server.logic.ws_protocol.JSON.handlers.auth.NetSessionRefreshHandler;
import java.util.Map; import java.util.Map;
@ -25,18 +25,18 @@ import java.util.Map;
public final class JsonHandlerRegistry { public final class JsonHandlerRegistry {
private static final Map<String, JsonMessageHandler> HANDLERS = Map.of( private static final Map<String, JsonMessageHandler> HANDLERS = Map.of(
"SessionRefresh", new NetSessionRefreshHandler(), "RefreshSession", new Net_RefreshSession_Handler(),
"AddUser", new NetAddUserHandler(), "AddUser", new NetAddUserHandler(),
"AuthSessionNewStep1", new NetAuthSessionNewStep1Handler(), "AuthChallenge", new Net_AuthChallenge_Handler(),
"AuthSessionNewStep2", new NetAuthSessionNewStep2Handler() "CreateAuthSession", new Net_CreateAuthSession__Handler()
// сюда потом добавишь другие операции // сюда потом добавишь другие операции
); );
private static final Map<String, Class<? extends NetRequest>> REQUEST_TYPES = Map.of( private static final Map<String, Class<? extends NetRequest>> REQUEST_TYPES = Map.of(
"SessionRefresh", NetSessionRefreshRequest.class, "RefreshSession", Net_RefreshSession_Request.class,
"AddUser", NetAddUserRequest.class, "AddUser", NetAddUserRequest.class,
"AuthSessionNewStep1", NetAuthSessionNewStep1Request.class, "AuthChallenge", Net_AuthChallenge_Request.class,
"AuthSessionNewStep2", NetAuthSessionNewStep2Request.class "CreateAuthSession", Net_CreateAuthSession_Request.class
); );
private JsonHandlerRegistry() { private JsonHandlerRegistry() {

View File

@ -0,0 +1,176 @@
Протокол создания новой сессии
📌 Общие правила JSON-протокола
Любой запрос от клиента имеет формат:
{
"op": "OperationName",
"requestId": "some-id",
"payload": { ... }
}
Ответ от сервера:
{
"op": "OperationName",
"requestId": "some-id",
"status": 200,
"payload": { "ok": true, ... }
}
Ошибка:
{
"op": "OperationName",
"requestId": "some-id",
"status": 4xx/5xx,
"payload": {
"ok": false,
"code": "ERROR_CODE",
"message": "Описание ошибки"
}
}
1. Добавление пользователя (AddUser)
Назначение: создать локальную запись пользователя с двумя ключами — loginKey и deviceKey.
📤 Запрос клиента
{
"op": "AddUser",
"requestId": "req-1",
"payload": {
"login": "anya4",
"loginId": 100212,
"bchId": 4222,
"loginKey": "BASE64_LOGIN_KEY",
"deviceKey": "BASE64_DEVICE_KEY",
"bchLimit": 1000000
}
}
🖥 Действия сервера
Проверяет корректность данных.
Вставляет запись в таблицу:
CREATE TABLE solana_users (
login TEXT NOT NULL,
loginId INTEGER PRIMARY KEY,
bchId INTEGER NOT NULL,
loginKey TEXT,
deviceKey TEXT,
bchLimit INTEGER
);
📥 Ответ
{
"op": "AddUser",
"requestId": "req-1",
"status": 200,
"payload": { "ok": true }
}
2. Шаг 1 — запрос временного пароля сессии
AuthChallenge
Назначение: сервер выдаёт клиенту временный sessionPwd.
Он потом будет включён в подписываемую строку.
📤 Запрос клиента
{
"op": "AuthChallenge",
"requestId": "req-2",
"payload": {
"login": "anya4"
}
}
🖥 Действия сервера
Находит пользователя по login.
Генерирует sessionPwd — случайный 32-байтовый base64.
Сохраняет sessionPwd во временный in-memory storage, привязанный к loginId.
📥 Ответ
{
"op": "AuthChallenge",
"requestId": "req-2",
"status": 200,
"payload": {
"ok": true,
"sessionPwd": "BASE64_SESSION_PWD"
}
}
3. Шаг 2 — подтверждение подписью и создание сессии
CreateAuthSession
📌 Клиент подписывает строку:
preimage = "AUTHORIFICATED:" + timeMs + sessionPwd
timeMs — timestamp клиента (UTC).
sessionPwd — строка с шага 1.
signatureB64 — Ed25519подпись preimage приватным ключом deviceKey.
📤 Запрос клиента
{
"op": "CreateAuthSession",
"requestId": "req-3",
"payload": {
"storagePwd": "BASE64_32_BYTES",
"timeMs": 1765298068436,
"signatureB64": "BASE64_SIGNATURE"
}
}
🔍 Валидация сервера
Проверяет timeMs:
не старше 30 секунд (now - timeMs <= 30s);
не в сильном будущем (опционально).
Восстанавливает preimage.
Находит deviceKey пользователя.
Проверяет Ed25519-подпись.
Создаёт sessionId — base64 от 32 байт.
Создаёт запись ActiveSession:
CREATE TABLE active_sessions (
sessionId TEXT PRIMARY KEY,
loginId INTEGER NOT NULL,
sessionPwd TEXT NOT NULL,
storagePwd TEXT NOT NULL,
sessionCreatedAtMs INTEGER NOT NULL,
lastAuthirificatedAtMs INTEGER NOT NULL,
pushEndpoint TEXT,
pushP256dhKey TEXT,
pushAuthKey TEXT
);
📥 Ответ сервера (успех)
{
"op": "CreateAuthSession",
"requestId": "req-3",
"status": 200,
"payload": {
"ok": true,
"sessionId": "BASE64_SESSION_ID"
}
}
📘 Итоговая схема создания сессии
AddUser → AuthChallenge → CreateAuthSession → Session Created

View File

@ -10,7 +10,7 @@ import server.logic.ws_protocol.JSON.entyties.NetRequest;
* *
* Формат входящего JSON: * Формат входящего JSON:
* { * {
* "op": "AuthSessionNewStep1", * "op": "AuthChallenge",
* "requestId": "...", * "requestId": "...",
* "payload": { * "payload": {
* "login": "someLogin" * "login": "someLogin"
@ -19,7 +19,7 @@ import server.logic.ws_protocol.JSON.entyties.NetRequest;
* *
* Формат успешного ответа: * Формат успешного ответа:
* { * {
* "op": "AuthSessionNewStep1", * "op": "AuthChallenge",
* "requestId": "...", * "requestId": "...",
* "status": 200, * "status": 200,
* "payload": { * "payload": {
@ -27,7 +27,7 @@ import server.logic.ws_protocol.JSON.entyties.NetRequest;
* } * }
* } * }
*/ */
public class NetAuthSessionNewStep1Request extends NetRequest { public class Net_AuthChallenge_Request extends NetRequest {
/** /**
* Логин пользователя, для которого запускается авторизация. * Логин пользователя, для которого запускается авторизация.

View File

@ -3,14 +3,14 @@ package server.logic.ws_protocol.JSON.entyties.Auth;
import server.logic.ws_protocol.JSON.entyties.NetResponse; import server.logic.ws_protocol.JSON.entyties.NetResponse;
/** /**
* Ответ на AuthSessionNewStep1. * Ответ на AuthChallenge.
* *
* При успехе сервер возвращает временный секрет sessionPwd, * При успехе сервер возвращает временный секрет sessionPwd,
* который клиент обязан использовать на втором шаге при формировании подписи. * который клиент обязан использовать на втором шаге при формировании подписи.
* *
* JSON: * JSON:
* { * {
* "op": "AuthSessionNewStep1", * "op": "AuthChallenge",
* "requestId": "...", * "requestId": "...",
* "status": 200, * "status": 200,
* "payload": { * "payload": {
@ -18,7 +18,7 @@ import server.logic.ws_protocol.JSON.entyties.NetResponse;
* } * }
* } * }
*/ */
public class NetAuthSessionNewStep1Response extends NetResponse { public class Net_AuthChallenge_Response extends NetResponse {
/** /**
* Временный секрет, сгенерированный сервером. * Временный секрет, сгенерированный сервером.

View File

@ -15,7 +15,7 @@ import server.logic.ws_protocol.JSON.entyties.NetRequest;
* *
* Формат входящего JSON: * Формат входящего JSON:
* { * {
* "op": "AuthSessionNewStep2", * "op": "CreateAuthSession",
* "requestId": "...", * "requestId": "...",
* "payload": { * "payload": {
* "storagePwd": "base64-строка-от-32-байт", * "storagePwd": "base64-строка-от-32-байт",
@ -27,7 +27,7 @@ import server.logic.ws_protocol.JSON.entyties.NetRequest;
* При успешной проверке подписи сервер создаёт запись в active_sessions * При успешной проверке подписи сервер создаёт запись в active_sessions
* и возвращает sessionId (base64-строка от 32 байт). * и возвращает sessionId (base64-строка от 32 байт).
*/ */
public class NetAuthSessionNewStep2Request extends NetRequest { public class Net_CreateAuthSession_Request extends NetRequest {
/** Клиентский пароль для хранения данных (base64 от 32 байт). */ /** Клиентский пароль для хранения данных (base64 от 32 байт). */
private String storagePwd; private String storagePwd;

View File

@ -3,14 +3,14 @@ package server.logic.ws_protocol.JSON.entyties.Auth;
import server.logic.ws_protocol.JSON.entyties.NetResponse; import server.logic.ws_protocol.JSON.entyties.NetResponse;
/** /**
* Ответ на AuthSessionNewStep2. * Ответ на CreateAuthSession.
* *
* При успехе сервер создаёт запись в active_sessions * При успехе сервер создаёт запись в active_sessions
* и возвращает идентификатор сессии sessionId. * и возвращает идентификатор сессии sessionId.
* *
* JSON: * JSON:
* { * {
* "op": "AuthSessionNewStep2", * "op": "CreateAuthSession",
* "requestId": "...", * "requestId": "...",
* "status": 200, * "status": 200,
* "payload": { * "payload": {
@ -18,7 +18,7 @@ import server.logic.ws_protocol.JSON.entyties.NetResponse;
* } * }
* } * }
*/ */
public class NetAuthSessionNewStep2Response extends NetResponse { public class Net_CreateAuthSession_Response extends NetResponse {
/** Идентификатор сессии, base64 от 32 байт. */ /** Идентификатор сессии, base64 от 32 байт. */
private String sessionId; private String sessionId;

View File

@ -3,7 +3,7 @@ package server.logic.ws_protocol.JSON.entyties.Auth;
import server.logic.ws_protocol.JSON.entyties.NetRequest; import server.logic.ws_protocol.JSON.entyties.NetRequest;
/** /**
* Запрос SessionRefresh. * Запрос RefreshSession.
* *
* Используется для повторного входа без повторной подписи: * Используется для повторного входа без повторной подписи:
* клиент хранит sessionId и sessionPwd, которые получил на шаге 2. * клиент хранит sessionId и sessionPwd, которые получил на шаге 2.
@ -14,7 +14,7 @@ import server.logic.ws_protocol.JSON.entyties.NetRequest;
* "sessionPwd": "base64-sessionPwd" * "sessionPwd": "base64-sessionPwd"
* } * }
*/ */
public class NetSessionRefreshRequest extends NetRequest { public class Net_RefreshSession_Request extends NetRequest {
private String sessionId; private String sessionId;
private String sessionPwd; private String sessionPwd;

View File

@ -3,14 +3,14 @@ package server.logic.ws_protocol.JSON.entyties.Auth;
import server.logic.ws_protocol.JSON.entyties.NetResponse; import server.logic.ws_protocol.JSON.entyties.NetResponse;
/** /**
* Успешный ответ на SessionRefresh. * Успешный ответ на RefreshSession.
* *
* Дополнительно к статусу 200 сервер возвращает storagePwd, * Дополнительно к статусу 200 сервер возвращает storagePwd,
* чтобы клиент мог восстановить/синхронизировать локальное хранилище. * чтобы клиент мог восстановить/синхронизировать локальное хранилище.
* *
* JSON: * JSON:
* { * {
* "op": "SessionRefresh", * "op": "RefreshSession",
* "requestId": "...", * "requestId": "...",
* "status": 200, * "status": 200,
* "payload": { * "payload": {
@ -18,7 +18,7 @@ import server.logic.ws_protocol.JSON.entyties.NetResponse;
* } * }
* } * }
*/ */
public class NetSessionRefreshResponse extends NetResponse { public class Net_RefreshSession_Response extends NetResponse {
/** Пароль хранилища, сохранённый в сессии (storagePwd). */ /** Пароль хранилища, сохранённый в сессии (storagePwd). */
private String storagePwd; private String storagePwd;

View File

@ -0,0 +1,74 @@
Протокол обновления существующей сессии
1. Назначение
RefreshSession используется для:
проверки, что клиент всё ещё владеет правильным sessionPwd;
продления “живучести” сессии;
возврата клиенту его storagePwd.
2. Формат запроса RefreshSession
{
"op": "RefreshSession",
"requestId": "abc-1",
"payload": {
"sessionId": "BASE64_SESSION_ID",
"sessionPwd": "BASE64_SESSION_PWD"
}
}
3. Действия сервера при RefreshSession
1) Поиск записи в active_sessions
SELECT * FROM active_sessions WHERE sessionId = ?
Если нет — ошибка:
{
"op": "RefreshSession",
"status": 404,
"payload": {
"ok": false,
"code": "SESSION_NOT_FOUND",
"message": "Сессия не найдена"
}
}
2) Проверка поля sessionPwd
Сравнивается payload.sessionPwd с полем active_sessions.sessionPwd.
Если неверно:
{
"op": "RefreshSession",
"status": 401,
"payload": {
"ok": false,
"code": "SESSION_PWD_MISMATCH",
"message": "Неверный пароль сессии"
}
}
3) Обновление времени последней авторизации
UPDATE active_sessions
SET lastAuthirificatedAtMs = ?
WHERE sessionId = ?
4) Возвращение клиенту актуального storagePwd
{
"op": "RefreshSession",
"requestId": "abc-1",
"status": 200,
"payload": {
"ok": true,
"storagePwd": "BASE64_STORAGE_PWD"
}
}
4. Итоговая схема RefreshSession
Client → RefreshSession(sessionId, sessionPwd)
→ Server validates → updates lastAuth
→ returns storagePwd

View File

@ -0,0 +1,40 @@
Net_AuthChallenge_Request — запрос вызова авторизации
Net_CreateAuthSession_Request — создание авторизационной сессии
Net_CloseAuthSession_Request — закрытие (завершение) сессии
Net_ListSessions_Request — получение списка активных сессий
Net_RefreshSession_Request — обновление / продление сессии
Net_AuthChallenge_Request — запрос вызова авторизации
Net_CreateAuthSession_Request — создание авторизационной сессии
закрытие сессии
Net_CloseAuthSession_Request — закрытие (завершение) сессии
елси уже авторифицирован то:
Net_CloseAuthSession_Request с параметром номер сесии или без параметра если прям эту сесиию
если не авторифицирован то:
Net_AuthChallenge_Request — запрос вызова авторизации
Net_CloseAuthSession_Request с параметром номер сесии для закрытия и время и цп для подтвержедния
получение списка сессий
Net_AuthChallenge_Request — запрос вызова авторизации
Net_ListSessions_Request — получение списка активных сессий
Net_RefreshSession_Request — обновление / продление сессии
план что сделать
Додумать названия что бы было общее новое приветствие ( и поле назвать число для проверки а не пароль )
или от него или новая сессия (и плюс в ней новый пароль передавать)
или получить список сесссий
или удалить сессию
И добавить хранимую инфу по сессии

View File

@ -2,8 +2,8 @@ package server.logic.ws_protocol.JSON.handlers.auth;
import server.logic.ws_protocol.JSON.ConnectionContext; import server.logic.ws_protocol.JSON.ConnectionContext;
import server.logic.ws_protocol.JSON.entyties.*; import server.logic.ws_protocol.JSON.entyties.*;
import server.logic.ws_protocol.JSON.entyties.Auth.NetAuthSessionNewStep1Request; import server.logic.ws_protocol.JSON.entyties.Auth.Net_AuthChallenge_Request;
import server.logic.ws_protocol.JSON.entyties.Auth.NetAuthSessionNewStep1Response; import server.logic.ws_protocol.JSON.entyties.Auth.Net_AuthChallenge_Response;
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory; import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
import server.logic.ws_protocol.WireCodes; import server.logic.ws_protocol.WireCodes;
@ -13,14 +13,14 @@ import shine.db.entities.SolanaUser;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Base64; import java.util.Base64;
public class NetAuthSessionNewStep1Handler implements JsonMessageHandler { public class Net_AuthChallenge_Handler implements JsonMessageHandler {
private static final SecureRandom RANDOM = new SecureRandom(); private static final SecureRandom RANDOM = new SecureRandom();
@Override @Override
public NetResponse handle(NetRequest baseReq, ConnectionContext ctx) throws Exception { public NetResponse handle(NetRequest baseReq, ConnectionContext ctx) throws Exception {
NetAuthSessionNewStep1Request req = (NetAuthSessionNewStep1Request) baseReq; Net_AuthChallenge_Request req = (Net_AuthChallenge_Request) baseReq;
String login = req.getLogin(); String login = req.getLogin();
if (login == null || login.isBlank()) { if (login == null || login.isBlank()) {
@ -66,7 +66,7 @@ public class NetAuthSessionNewStep1Handler implements JsonMessageHandler {
ctx.setSessionPwd(sessionPwd); ctx.setSessionPwd(sessionPwd);
// 5) Формируем ответ // 5) Формируем ответ
NetAuthSessionNewStep1Response resp = new NetAuthSessionNewStep1Response(); Net_AuthChallenge_Response resp = new Net_AuthChallenge_Response();
resp.setOp(req.getOp()); resp.setOp(req.getOp());
resp.setRequestId(req.getRequestId()); resp.setRequestId(req.getRequestId());
resp.setStatus(WireCodes.Status.OK); resp.setStatus(WireCodes.Status.OK);

View File

@ -4,10 +4,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import server.logic.ws_protocol.JSON.ActiveConnectionsRegistry; import server.logic.ws_protocol.JSON.ActiveConnectionsRegistry;
import server.logic.ws_protocol.JSON.ConnectionContext; import server.logic.ws_protocol.JSON.ConnectionContext;
import server.logic.ws_protocol.JSON.entyties.Auth.Net_CreateAuthSession_Response;
import server.logic.ws_protocol.JSON.entyties.NetRequest; import server.logic.ws_protocol.JSON.entyties.NetRequest;
import server.logic.ws_protocol.JSON.entyties.NetResponse; import server.logic.ws_protocol.JSON.entyties.NetResponse;
import server.logic.ws_protocol.JSON.entyties.Auth.NetAuthSessionNewStep2Request; import server.logic.ws_protocol.JSON.entyties.Auth.Net_CreateAuthSession_Request;
import server.logic.ws_protocol.JSON.entyties.Auth.NetAuthSessionNewStep2Response;
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory; import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
import server.logic.ws_protocol.WireCodes; import server.logic.ws_protocol.WireCodes;
@ -43,16 +43,16 @@ import java.util.Base64;
* - pushEndpoint / pushP256dhKey / pushAuthKey остаются пустыми; * - pushEndpoint / pushP256dhKey / pushAuthKey остаются пустыми;
* - возвращается sessionId в ответе. * - возвращается sessionId в ответе.
*/ */
public class NetAuthSessionNewStep2Handler implements JsonMessageHandler { public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
private static final Logger log = LoggerFactory.getLogger(NetAuthSessionNewStep2Handler.class); private static final Logger log = LoggerFactory.getLogger(Net_CreateAuthSession__Handler.class);
private static final SecureRandom RANDOM = new SecureRandom(); private static final SecureRandom RANDOM = new SecureRandom();
private static final long ALLOWED_SKEW_MS = 30_000L; private static final long ALLOWED_SKEW_MS = 30_000L;
@Override @Override
public NetResponse handle(NetRequest baseReq, ConnectionContext ctx) throws Exception { public NetResponse handle(NetRequest baseReq, ConnectionContext ctx) throws Exception {
NetAuthSessionNewStep2Request req = (NetAuthSessionNewStep2Request) baseReq; Net_CreateAuthSession_Request req = (Net_CreateAuthSession_Request) baseReq;
// --- базовые проверки контекста --- // --- базовые проверки контекста ---
if (ctx == null || ctx.getSolanaUser() == null || ctx.getSessionPwd() == null) { if (ctx == null || ctx.getSolanaUser() == null || ctx.getSessionPwd() == null) {
@ -198,7 +198,7 @@ public class NetAuthSessionNewStep2Handler implements JsonMessageHandler {
ActiveConnectionsRegistry.getInstance().register(ctx); ActiveConnectionsRegistry.getInstance().register(ctx);
// --- формируем ответ --- // --- формируем ответ ---
NetAuthSessionNewStep2Response resp = new NetAuthSessionNewStep2Response(); Net_CreateAuthSession_Response resp = new Net_CreateAuthSession_Response();
resp.setOp(req.getOp()); resp.setOp(req.getOp());
resp.setRequestId(req.getRequestId()); resp.setRequestId(req.getRequestId());
resp.setStatus(WireCodes.Status.OK); resp.setStatus(WireCodes.Status.OK);

View File

@ -4,10 +4,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import server.logic.ws_protocol.JSON.ActiveConnectionsRegistry; import server.logic.ws_protocol.JSON.ActiveConnectionsRegistry;
import server.logic.ws_protocol.JSON.ConnectionContext; import server.logic.ws_protocol.JSON.ConnectionContext;
import server.logic.ws_protocol.JSON.entyties.Auth.Net_RefreshSession_Request;
import server.logic.ws_protocol.JSON.entyties.Auth.Net_RefreshSession_Response;
import server.logic.ws_protocol.JSON.entyties.NetRequest; import server.logic.ws_protocol.JSON.entyties.NetRequest;
import server.logic.ws_protocol.JSON.entyties.NetResponse; import server.logic.ws_protocol.JSON.entyties.NetResponse;
import server.logic.ws_protocol.JSON.entyties.Auth.NetSessionRefreshRequest;
import server.logic.ws_protocol.JSON.entyties.Auth.NetSessionRefreshResponse;
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory; import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
import server.logic.ws_protocol.WireCodes; import server.logic.ws_protocol.WireCodes;
@ -19,7 +19,7 @@ import shine.db.entities.SolanaUser;
import java.sql.SQLException; import java.sql.SQLException;
/** /**
* Хэндлер SessionRefresh. * Хэндлер RefreshSession.
* *
* При успешной проверке sessionId + sessionPwd: * При успешной проверке sessionId + sessionPwd:
* - подтягивает пользователя по loginId из сессии; * - подтягивает пользователя по loginId из сессии;
@ -27,13 +27,13 @@ import java.sql.SQLException;
* - обновляет lastAuthirificatedAtMs в БД на текущее время; * - обновляет lastAuthirificatedAtMs в БД на текущее время;
* - возвращает storagePwd в payload. * - возвращает storagePwd в payload.
*/ */
public class NetSessionRefreshHandler implements JsonMessageHandler { public class Net_RefreshSession_Handler implements JsonMessageHandler {
private static final Logger log = LoggerFactory.getLogger(NetSessionRefreshHandler.class); private static final Logger log = LoggerFactory.getLogger(Net_RefreshSession_Handler.class);
@Override @Override
public NetResponse handle(NetRequest request, ConnectionContext ctx) throws Exception { public NetResponse handle(NetRequest request, ConnectionContext ctx) throws Exception {
NetSessionRefreshRequest req = (NetSessionRefreshRequest) request; Net_RefreshSession_Request req = (Net_RefreshSession_Request) request;
String sessionId = req.getSessionId(); String sessionId = req.getSessionId();
String sessionPwd = req.getSessionPwd(); String sessionPwd = req.getSessionPwd();
@ -135,7 +135,7 @@ public class NetSessionRefreshHandler implements JsonMessageHandler {
} }
// Возвращаем OK + storagePwd // Возвращаем OK + storagePwd
NetSessionRefreshResponse resp = new NetSessionRefreshResponse(); Net_RefreshSession_Response resp = new Net_RefreshSession_Response();
resp.setOp(req.getOp()); resp.setOp(req.getOp());
resp.setRequestId(req.getRequestId()); resp.setRequestId(req.getRequestId());
resp.setStatus(WireCodes.Status.OK); resp.setStatus(WireCodes.Status.OK);

View File

@ -12,9 +12,9 @@ public class TestJsonWsClient2 {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
String uri = "ws://localhost:7070/ws"; String uri = "ws://localhost:7070/ws";
String jsonRequestSessionRefresh = """ String jsonRequestRefreshSession = """
{ {
"op": "SessionRefresh", "op": "RefreshSession",
"requestId": "test-1", "requestId": "test-1",
"payload": { "payload": {
"sessionId": 123, "sessionId": 123,
@ -38,9 +38,9 @@ public class TestJsonWsClient2 {
} }
"""; """;
String jsonRequestAuthSessionNewStep1 = """ String jsonRequestAuthChallenge = """
{ {
"op": "AuthSessionNewStep1", "op": "AuthChallenge",
"requestId": "test-auth-1", "requestId": "test-auth-1",
"payload": { "payload": {
"login": "anya1111" "login": "anya1111"
@ -49,8 +49,8 @@ public class TestJsonWsClient2 {
"""; """;
// Что тестируем сейчас: // Что тестируем сейчас:
String jsonRequest = jsonRequestAuthSessionNewStep1; String jsonRequest = jsonRequestAuthChallenge;
// String jsonRequest = jsonRequestSessionRefresh; // String jsonRequest = jsonRequestRefreshSession;
// String jsonRequest = jsonRequestAddUser; // String jsonRequest = jsonRequestAddUser;
System.out.println("Подключаемся к " + uri); System.out.println("Подключаемся к " + uri);

View File

@ -20,18 +20,18 @@ import java.util.concurrent.CountDownLatch;
* 1) AddUser добавляем пользователя в локальную БД * 1) AddUser добавляем пользователя в локальную БД
* (loginKey и deviceKey разные). * (loginKey и deviceKey разные).
* *
* 2) AuthSessionNewStep1 запрашиваем sessionPwd. * 2) AuthChallenge запрашиваем sessionPwd.
* *
* 3) AuthSessionNewStep2 подтверждаем владение deviceKey, * 3) CreateAuthSession подтверждаем владение deviceKey,
* создаётся сессия, сервер возвращает sessionId (строка). * создаётся сессия, сервер возвращает sessionId (строка).
* *
* 4) Новое подключение: * 4) Новое подключение:
* - отправляем SessionRefresh с тем же sessionId, * - отправляем RefreshSession с тем же sessionId,
* но заведомо неверным sessionPwd * но заведомо неверным sessionPwd
* (в консоль пишем: ожидаем ОТРИЦАТЕЛЬНЫЙ ответ). * (в консоль пишем: ожидаем ОТРИЦАТЕЛЬНЫЙ ответ).
* *
* 5) Ещё одно новое подключение: * 5) Ещё одно новое подключение:
* - отправляем SessionRefresh с sessionId * - отправляем RefreshSession с sessionId
* и корректным sessionPwd * и корректным sessionPwd
* (в консоль пишем: ожидаем УСПЕШНЫЙ ответ). * (в консоль пишем: ожидаем УСПЕШНЫЙ ответ).
*/ */
@ -72,13 +72,13 @@ public class Test_AddUser_and_Authorification {
// --- Глобальные переменные между сценариями --- // --- Глобальные переменные между сценариями ---
/** sessionPwd, выданный на шаге AuthSessionNewStep1. */ /** sessionPwd, выданный на шаге AuthChallenge. */
private static String GLOBAL_SESSION_PWD; private static String GLOBAL_SESSION_PWD;
/** sessionId (строка, base64-32 байта), выданный на шаге AuthSessionNewStep2. */ /** sessionId (строка, base64-32 байта), выданный на шаге CreateAuthSession. */
private static String GLOBAL_SESSION_ID; private static String GLOBAL_SESSION_ID;
/** storagePwd, который мы отправили при AuthSessionNewStep2 (для информации). */ /** storagePwd, который мы отправили при CreateAuthSession (для информации). */
private static String GLOBAL_STORAGE_PWD_SENT; private static String GLOBAL_STORAGE_PWD_SENT;
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
@ -87,11 +87,11 @@ public class Test_AddUser_and_Authorification {
// Сценарий 1: регистрация + первичная авторизация // Сценарий 1: регистрация + первичная авторизация
runScenario_AddUser_And_FirstAuth(); runScenario_AddUser_And_FirstAuth();
// Сценарий 2: новое подключение, SessionRefresh с неверным sessionPwd // Сценарий 2: новое подключение, RefreshSession с неверным sessionPwd
runScenario_SessionRefresh_WrongPwd(); runScenario_RefreshSession_WrongPwd();
// Сценарий 3: новое подключение, SessionRefresh с корректным sessionPwd // Сценарий 3: новое подключение, RefreshSession с корректным sessionPwd
runScenario_SessionRefresh_CorrectPwd(); runScenario_RefreshSession_CorrectPwd();
System.out.println("Все тесты завершены, выходим."); System.out.println("Все тесты завершены, выходим.");
} }
@ -102,7 +102,7 @@ public class Test_AddUser_and_Authorification {
private static void runScenario_AddUser_And_FirstAuth() throws Exception { private static void runScenario_AddUser_And_FirstAuth() throws Exception {
System.out.println(); System.out.println();
System.out.println("=== СЦЕНАРИЙ 1: AddUser + AuthSessionNewStep1 + AuthSessionNewStep2 ==="); System.out.println("=== СЦЕНАРИЙ 1: AddUser + AuthChallenge + CreateAuthSession ===");
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
@ -132,7 +132,7 @@ public class Test_AddUser_and_Authorification {
case 1 -> { case 1 -> {
String json = buildAuthStep1Json(); String json = buildAuthStep1Json();
System.out.println(); System.out.println();
System.out.println("📤 [S1 / Шаг 2] Отправляем AuthSessionNewStep1:"); System.out.println("📤 [S1 / Шаг 2] Отправляем AuthChallenge:");
System.out.println(json); System.out.println(json);
webSocket.sendText(json, true); webSocket.sendText(json, true);
} }
@ -140,7 +140,7 @@ public class Test_AddUser_and_Authorification {
GLOBAL_STORAGE_PWD_SENT = generateFakeStoragePwd(); GLOBAL_STORAGE_PWD_SENT = generateFakeStoragePwd();
String json = buildAuthStep2Json(GLOBAL_SESSION_PWD, GLOBAL_STORAGE_PWD_SENT); String json = buildAuthStep2Json(GLOBAL_SESSION_PWD, GLOBAL_STORAGE_PWD_SENT);
System.out.println(); System.out.println();
System.out.println("📤 [S1 / Шаг 3] Отправляем AuthSessionNewStep2 (подпись deviceKey):"); System.out.println("📤 [S1 / Шаг 3] Отправляем CreateAuthSession (подпись deviceKey):");
System.out.println(json); System.out.println(json);
webSocket.sendText(json, true); webSocket.sendText(json, true);
} }
@ -202,12 +202,12 @@ public class Test_AddUser_and_Authorification {
} }
// ========================================================== // ==========================================================
// SCENARIO 2: SessionRefresh с неправильным паролем // SCENARIO 2: RefreshSession с неправильным паролем
// ========================================================== // ==========================================================
private static void runScenario_SessionRefresh_WrongPwd() throws Exception { private static void runScenario_RefreshSession_WrongPwd() throws Exception {
System.out.println(); System.out.println();
System.out.println("=== СЦЕНАРИЙ 2: SessionRefresh с НЕВЕРНЫМ sessionPwd ==="); System.out.println("=== СЦЕНАРИЙ 2: RefreshSession с НЕВЕРНЫМ sessionPwd ===");
System.out.println("Ожидаем ОТРИЦАТЕЛЬНЫЙ ответ сервера (UNVERIFIED / SESSION_PWD_MISMATCH и т.п.)"); System.out.println("Ожидаем ОТРИЦАТЕЛЬНЫЙ ответ сервера (UNVERIFIED / SESSION_PWD_MISMATCH и т.п.)");
if (GLOBAL_SESSION_ID == null || GLOBAL_SESSION_PWD == null) { if (GLOBAL_SESSION_ID == null || GLOBAL_SESSION_PWD == null) {
@ -229,9 +229,9 @@ public class Test_AddUser_and_Authorification {
System.out.println("✅ [S2] WebSocket подключен"); System.out.println("✅ [S2] WebSocket подключен");
webSocket.request(1); webSocket.request(1);
String json = buildSessionRefreshJson(GLOBAL_SESSION_ID, wrongPwd, "test-refresh-wrong-1"); String json = buildRefreshSessionJson(GLOBAL_SESSION_ID, wrongPwd, "test-refresh-wrong-1");
System.out.println(); System.out.println();
System.out.println("📤 [S2] Отправляем SessionRefresh с НЕВЕРНЫМ sessionPwd:"); System.out.println("📤 [S2] Отправляем RefreshSession с НЕВЕРНЫМ sessionPwd:");
System.out.println(json); System.out.println(json);
webSocket.sendText(json, true); webSocket.sendText(json, true);
Listener.super.onOpen(webSocket); Listener.super.onOpen(webSocket);
@ -274,12 +274,12 @@ public class Test_AddUser_and_Authorification {
} }
// ========================================================== // ==========================================================
// SCENARIO 3: SessionRefresh с правильными данными // SCENARIO 3: RefreshSession с правильными данными
// ========================================================== // ==========================================================
private static void runScenario_SessionRefresh_CorrectPwd() throws Exception { private static void runScenario_RefreshSession_CorrectPwd() throws Exception {
System.out.println(); System.out.println();
System.out.println("=== СЦЕНАРИЙ 3: SessionRefresh с КОРРЕКТНЫМ sessionPwd ==="); System.out.println("=== СЦЕНАРИЙ 3: RefreshSession с КОРРЕКТНЫМ sessionPwd ===");
System.out.println("Ожидаем УСПЕШНЫЙ ответ сервера (status=200),"); System.out.println("Ожидаем УСПЕШНЫЙ ответ сервера (status=200),");
System.out.println(" а в payload должен вернуться актуальный storagePwd (по твоей схеме)."); System.out.println(" а в payload должен вернуться актуальный storagePwd (по твоей схеме).");
@ -299,9 +299,9 @@ public class Test_AddUser_and_Authorification {
System.out.println("✅ [S3] WebSocket подключен"); System.out.println("✅ [S3] WebSocket подключен");
webSocket.request(1); webSocket.request(1);
String json = buildSessionRefreshJson(GLOBAL_SESSION_ID, GLOBAL_SESSION_PWD, "test-refresh-ok-1"); String json = buildRefreshSessionJson(GLOBAL_SESSION_ID, GLOBAL_SESSION_PWD, "test-refresh-ok-1");
System.out.println(); System.out.println();
System.out.println("📤 [S3] Отправляем SessionRefresh с КОРРЕКТНЫМ sessionPwd:"); System.out.println("📤 [S3] Отправляем RefreshSession с КОРРЕКТНЫМ sessionPwd:");
System.out.println(json); System.out.println(json);
webSocket.sendText(json, true); webSocket.sendText(json, true);
Listener.super.onOpen(webSocket); Listener.super.onOpen(webSocket);
@ -379,7 +379,7 @@ public class Test_AddUser_and_Authorification {
private static String buildAuthStep1Json() { private static String buildAuthStep1Json() {
return """ return """
{ {
"op": "AuthSessionNewStep1", "op": "AuthChallenge",
"requestId": "test-auth-1", "requestId": "test-auth-1",
"payload": { "payload": {
"login": "%s" "login": "%s"
@ -410,7 +410,7 @@ public class Test_AddUser_and_Authorification {
return """ return """
{ {
"op": "AuthSessionNewStep2", "op": "CreateAuthSession",
"requestId": "test-auth-2", "requestId": "test-auth-2",
"payload": { "payload": {
"storagePwd": "%s", "storagePwd": "%s",
@ -425,11 +425,11 @@ public class Test_AddUser_and_Authorification {
); );
} }
// 4) SessionRefresh: всё в payload // 4) RefreshSession: всё в payload
private static String buildSessionRefreshJson(String sessionId, String sessionPwd, String requestId) { private static String buildRefreshSessionJson(String sessionId, String sessionPwd, String requestId) {
return """ return """
{ {
"op": "SessionRefresh", "op": "RefreshSession",
"requestId": "%s", "requestId": "%s",
"payload": { "payload": {
"sessionId": "%s", "sessionId": "%s",

View File

@ -32,13 +32,13 @@ public class Test_SessionRefreshClient {
.join(); .join();
latch.await(); latch.await();
System.out.println("Тест SessionRefresh завершён, выходим."); System.out.println("Тест RefreshSession завершён, выходим.");
} }
private static String buildSessionRefreshJson() { private static String buildRefreshSessionJson() {
return """ return """
{ {
"op": "SessionRefresh", "op": "RefreshSession",
"requestId": "test-session-refresh-1", "requestId": "test-session-refresh-1",
"payload": { "payload": {
"sessionId": %d, "sessionId": %d,
@ -62,10 +62,10 @@ public class Test_SessionRefreshClient {
webSocket.request(1); // разрешаем принимать одно сообщение webSocket.request(1); // разрешаем принимать одно сообщение
// сразу отправляем запрос SessionRefresh // сразу отправляем запрос RefreshSession
String json = buildSessionRefreshJson(); String json = buildRefreshSessionJson();
System.out.println(); System.out.println();
System.out.println("📤 Отправляем SessionRefresh:"); System.out.println("📤 Отправляем RefreshSession:");
System.out.println(json); System.out.println(json);
webSocket.sendText(json, true); webSocket.sendText(json, true);
@ -81,7 +81,7 @@ public class Test_SessionRefreshClient {
System.out.println("-----------------------------------------------------"); System.out.println("-----------------------------------------------------");
// После одного ответа просто закрываем соединение // После одного ответа просто закрываем соединение
System.out.println("✅ Получен ответ на SessionRefresh, закрываем соединение"); System.out.println("✅ Получен ответ на RefreshSession, закрываем соединение");
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "session refresh test done"); webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "session refresh test done");
// запрашиваем следующее сообщение на всякий случай (хотя уже закрываемся) // запрашиваем следующее сообщение на всякий случай (хотя уже закрываемся)

View File

@ -0,0 +1,5 @@
package Test;
public class test1 {
}