This commit is contained in:
AidarKC
2025-12-05 10:56:34 +03:00
parent 5d8dd86c96
commit fc748a744c
23 changed files with 1069 additions and 307 deletions
@@ -1,8 +1,9 @@
package Test;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.net.http.WebSocket.Listener;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch;
@@ -0,0 +1,236 @@
package Test;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import utils.crypto.Ed25519Util;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.net.http.WebSocket.Listener;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch;
public class Test_AddUser_FirstAuth {
// Адрес сервера
private static final String WS_URI = "ws://localhost:7070/ws";
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
// Тестовые данные пользователя
private static final String TEST_LOGIN = "anya2";
private static final long TEST_LOGIN_ID = 100212L;
private static final long TEST_BCH_ID = 4222L;
private static final int TEST_BCH_LIMIT = 1_000_000;
// Тестовая пара ключей Ed25519 (стабильная, чтобы поведение не прыгало)
private static final byte[] TEST_PRIV_KEY;
private static final String TEST_PUBKEY_B64;
static {
// Можно сделать детерминированно от логина, чтобы всегда были одинаковые ключи
TEST_PRIV_KEY = Ed25519Util.generatePrivateKeyFromString("test-ed25519-" + TEST_LOGIN);
byte[] pub = Ed25519Util.derivePublicKey(TEST_PRIV_KEY);
TEST_PUBKEY_B64 = Ed25519Util.keyToBase64(pub);
}
public static void main(String[] args) throws Exception {
System.out.println("Подключаемся к " + WS_URI);
CountDownLatch latch = new CountDownLatch(1);
HttpClient client = HttpClient.newHttpClient();
ClientListener listener = new ClientListener(latch);
client.newWebSocketBuilder()
.buildAsync(URI.create(WS_URI), listener)
.join();
// Ждём, пока всё не завершится (успех/ошибка/закрытие)
latch.await();
System.out.println("Тест завершён, выходим.");
}
// --- вспомогательные билдера JSON-запросов ---
// 1) Добавление пользователя
private static String buildAddUserJson() {
return """
{
"op": "AddUser",
"requestId": "test-add-1",
"login": "%s",
"loginId": %d,
"bchId": %d,
"pubkey0": "%s",
"pubkey1": "%s",
"bchLimit": %d
}
""".formatted(
TEST_LOGIN,
TEST_LOGIN_ID,
TEST_BCH_ID,
TEST_PUBKEY_B64, // pubkey0
TEST_PUBKEY_B64, // pubkey1 (для теста можно тот же)
TEST_BCH_LIMIT
);
}
// 2) Шаг 1 авторизации: запрос sessionPwd
private static String buildAuthStep1Json() {
return """
{
"op": "AuthSessionNewStep1",
"requestId": "test-auth-1",
"login": "%s"
}
""".formatted(TEST_LOGIN);
}
// 3) Шаг 2 авторизации: подтверждение подписью
private static String buildAuthStep2Json(String sessionPwd) {
if (sessionPwd == null) {
sessionPwd = "";
}
long timeMs = System.currentTimeMillis();
// preimage = loginId + timeMs + sessionPwd
String preimageStr = String.valueOf(TEST_LOGIN_ID) + timeMs + sessionPwd;
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
// Подписываем приватным ключом
byte[] sig = Ed25519Util.sign(preimage, TEST_PRIV_KEY);
String sigB64 = Base64.getEncoder().encodeToString(sig);
return """
{
"op": "AuthSessionNewStep2",
"requestId": "test-auth-2",
"loginId": %d,
"sigNum": 0,
"timeMs": %d,
"signatureB64": "%s"
}
""".formatted(
TEST_LOGIN_ID,
timeMs,
sigB64
);
}
// ================== LISTENER ==================
// Внутренний Listener, который сам по шагам шлёт запросы и печатает ответы
private static class ClientListener implements Listener {
private final CountDownLatch latch;
private int step = 0; // 0 - AddUser, 1 - AuthStep1, 2 - AuthStep2
private String sessionPwdFromStep1;
ClientListener(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void onOpen(WebSocket webSocket) {
System.out.println("✅ WebSocket подключен");
// Разрешаем приём первого сообщения
webSocket.request(1);
sendNextRequest(webSocket);
Listener.super.onOpen(webSocket);
}
// Отправка следующего запроса в зависимости от шага
private void sendNextRequest(WebSocket webSocket) {
switch (step) {
case 0 -> {
String json = buildAddUserJson();
System.out.println();
System.out.println("📤 [Шаг 1] Отправляем AddUser:");
System.out.println(json);
webSocket.sendText(json, true);
}
case 1 -> {
String json = buildAuthStep1Json();
System.out.println();
System.out.println("📤 [Шаг 2] Отправляем AuthSessionNewStep1:");
System.out.println(json);
webSocket.sendText(json, true);
}
case 2 -> {
String json = buildAuthStep2Json(sessionPwdFromStep1);
System.out.println();
System.out.println("📤 [Шаг 3] Отправляем AuthSessionNewStep2 (подпись):");
System.out.println(json);
webSocket.sendText(json, true);
}
default -> {
System.out.println("✅ Все шаги выполнены, закрываем соединение");
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "all tests done");
}
}
}
@Override
public CompletionStage<?> onText(WebSocket webSocket,
CharSequence data,
boolean last) {
String message = data.toString();
System.out.println("📥 Ответ на шаг " + (step + 1) + ":");
System.out.println(message);
System.out.println("-----------------------------------------------------");
// Если это ответ на шаг 2 (AuthSessionNewStep1) — достаем sessionPwd из payload
if (step == 1) {
sessionPwdFromStep1 = extractSessionPwd(message);
System.out.println("🔑 Извлечён sessionPwd: " + sessionPwdFromStep1);
}
// Переходим к следующему шагу
step++;
sendNextRequest(webSocket);
// Запрашиваем следующее входящее сообщение
webSocket.request(1);
return CompletableFuture.completedFuture(null);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
System.out.println("❌ Ошибка WebSocket-клиента: " + error.getMessage());
error.printStackTrace(System.out);
latch.countDown();
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket,
int statusCode,
String reason) {
System.out.println("🔚 Соединение закрыто. Код=" + statusCode + ", причина=" + reason);
latch.countDown();
return CompletableFuture.completedFuture(null);
}
private String extractSessionPwd(String json) {
try {
JsonNode root = JSON_MAPPER.readTree(json);
JsonNode payload = root.get("payload");
if (payload != null && payload.has("sessionPwd")) {
return payload.get("sessionPwd").asText();
}
} catch (Exception e) {
System.out.println("⚠️ Не удалось распарсить sessionPwd из ответа: " + e.getMessage());
}
return null;
}
}
}
@@ -0,0 +1,109 @@
package Test;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.net.http.WebSocket.Listener;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch;
public class Test_SessionRefreshClient {
// Адрес сервера
private static final String WS_URI = "ws://localhost:7070/ws";
// ==== ЗДЕСЬ ПОДСТАВИШЬ СВОИ ДАННЫЕ СЕССИИ ====
private static final long SESSION_ID = 7599553208996461137L; // TODO: подставь реальный sessionId
private static final String SESSION_PWD = "11b3508f37ae7b41816f42031b90"; // TODO: подставь реальный sessionPwd
// =============================================
public static void main(String[] args) throws Exception {
System.out.println("Подключаемся к " + WS_URI);
CountDownLatch latch = new CountDownLatch(1);
HttpClient client = HttpClient.newHttpClient();
ClientListener listener = new ClientListener(latch);
client.newWebSocketBuilder()
.buildAsync(URI.create(WS_URI), listener)
.join();
latch.await();
System.out.println("Тест SessionRefresh завершён, выходим.");
}
private static String buildSessionRefreshJson() {
return """
{
"op": "SessionRefresh",
"requestId": "test-session-refresh-1",
"sessionId": %d,
"sessionPwd": "%s"
}
""".formatted(SESSION_ID, SESSION_PWD);
}
private static class ClientListener implements Listener {
private final CountDownLatch latch;
private boolean sent = false;
ClientListener(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void onOpen(WebSocket webSocket) {
System.out.println("✅ WebSocket подключен");
webSocket.request(1); // разрешаем принимать одно сообщение
// сразу отправляем запрос SessionRefresh
String json = buildSessionRefreshJson();
System.out.println();
System.out.println("📤 Отправляем SessionRefresh:");
System.out.println(json);
webSocket.sendText(json, true);
sent = true;
Listener.super.onOpen(webSocket);
}
@Override
public CompletionStage<?> onText(WebSocket webSocket,
CharSequence data,
boolean last) {
System.out.println("📥 Ответ от сервера:");
System.out.println(data.toString());
System.out.println("-----------------------------------------------------");
// После одного ответа просто закрываем соединение
System.out.println("✅ Получен ответ на SessionRefresh, закрываем соединение");
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "session refresh test done");
// запрашиваем следующее сообщение на всякий случай (хотя уже закрываемся)
webSocket.request(1);
return CompletableFuture.completedFuture(null);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
System.out.println("❌ Ошибка WebSocket-клиента: " + error.getMessage());
error.printStackTrace(System.out);
latch.countDown();
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket,
int statusCode,
String reason) {
System.out.println("🔚 Соединение закрыто. Код=" + statusCode + ", причина=" + reason);
latch.countDown();
return CompletableFuture.completedFuture(null);
}
}
}
-135
View File
@@ -1,135 +0,0 @@
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.net.http.WebSocket.Listener;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch;
public class TestJsonWsClient {
// Адрес сервера
private static final String WS_URI = "ws://localhost:7070/ws";
// Отдельные запросы
private static final String JSON_REQUEST_SESSION_REFRESH = """
{
"op": "SessionRefresh",
"requestId": "test-1",
"sessionId": 123,
"sessionPwd": "test-password"
}
""";
private static final String JSON_REQUEST_ADD_USER = """
{
"op": "AddUser",
"requestId": "test-add-1",
"login": "anya1111",
"loginId": 100211,
"bchId": 4222,
"pubkey0": "PUB0",
"pubkey1": "PUB1",
"bchLimit": 1000000
}
""";
private static final String JSON_REQUEST_AUTH_SESSION_NEW_STEP1 = """
{
"op": "AuthSessionNewStep1",
"requestId": "test-auth-1",
"login": "anya1111"
}
""";
// МАССИВ КОНСТАНТА с запросами — добавляешь сюда любые свои JSON
private static final String[] JSON_REQUESTS = {
JSON_REQUEST_SESSION_REFRESH,
JSON_REQUEST_ADD_USER,
JSON_REQUEST_AUTH_SESSION_NEW_STEP1
};
public static void main(String[] args) throws Exception {
System.out.println("Подключаемся к " + WS_URI);
CountDownLatch latch = new CountDownLatch(1);
HttpClient client = HttpClient.newHttpClient();
ClientListener listener = new ClientListener(JSON_REQUESTS, latch);
client.newWebSocketBuilder()
.buildAsync(URI.create(WS_URI), listener)
.join();
// Ждём, пока всё не завершится (успех/ошибка/закрытие)
latch.await();
System.out.println("Тест завершён, выходим.");
}
// Внутренний Listener, который сам по очереди шлёт запросы и печатает ответы
private static class ClientListener implements Listener {
private final String[] requests;
private final CountDownLatch latch;
private int index = 0; // какой запрос сейчас отправляем/ждём ответ
ClientListener(String[] requests, CountDownLatch latch) {
this.requests = requests;
this.latch = latch;
}
@Override
public void onOpen(WebSocket webSocket) {
System.out.println("✅ WebSocket подключен");
sendNextRequest(webSocket);
Listener.super.onOpen(webSocket);
}
// Отправка следующего запроса из массива
private void sendNextRequest(WebSocket webSocket) {
if (index < requests.length) {
String json = requests[index];
System.out.println();
System.out.println("📤 Отправляем запрос " + (index + 1) + " из " + requests.length + ":");
System.out.println(json);
webSocket.sendText(json, true);
} else {
System.out.println("✅ Все запросы отправлены, закрываем соединение");
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "all tests done");
}
}
@Override
public CompletionStage<?> onText(WebSocket webSocket,
CharSequence data,
boolean last) {
// Ответ на текущий запрос (с индексом index)
System.out.println("📥 Ответ на запрос " + (index + 1) + ":");
System.out.println(data.toString());
System.out.println("-----------------------------------------------------");
// Переходим к следующему запросу
index++;
sendNextRequest(webSocket);
return CompletableFuture.completedFuture(null);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
System.out.println("❌ Ошибка WebSocket-клиента: " + error.getMessage());
error.printStackTrace(System.out);
latch.countDown();
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket,
int statusCode,
String reason) {
System.out.println("🔚 Соединение закрыто. Код=" + statusCode + ", причина=" + reason);
latch.countDown();
return CompletableFuture.completedFuture(null);
}
}
}