Вроде всё доделал. Авторификацию. (осталось закрытие сессии и получение списка активных сессии)
This commit is contained in:
AidarKC 2025-12-10 16:18:32 +03:00
parent 00fc9e3926
commit 7072882b0b
3 changed files with 82 additions and 19 deletions

View File

@ -14,6 +14,10 @@ public final class ClientInfoService {
private ClientInfoService() { }
/**
* Собирает строку с информацией о клиенте:
* User-Agent, client-hints и удалённый IP.
*/
public static String buildClientInfoString(Session wsSession) {
if (wsSession == null) {
return CLIENT_INFO_UNKNOWN;
@ -29,14 +33,8 @@ public final class ClientInfoService {
String secChPlatform = getFirstHeader(req, "Sec-CH-UA-Platform");
String secChMobile = getFirstHeader(req, "Sec-CH-UA-Mobile");
// --- Исправленный блок определения IP ---
String remoteIp = "";
SocketAddress rawAddr = wsSession.getRemoteAddress();
if (rawAddr instanceof InetSocketAddress inet) {
if (inet.getAddress() != null) {
remoteIp = inet.getAddress().getHostAddress();
}
}
// IP берём через общий метод, чтобы не дублировать логику
String remoteIp = extractClientIp(wsSession);
StringBuilder sb = new StringBuilder();
@ -55,7 +53,7 @@ public final class ClientInfoService {
appendSep(sb);
sb.append("mobile=").append(secChMobile);
}
if (!remoteIp.isEmpty()) {
if (remoteIp != null && !remoteIp.isEmpty()) {
appendSep(sb);
sb.append("remote=").append(remoteIp);
}
@ -64,6 +62,49 @@ public final class ClientInfoService {
return result.isEmpty() ? CLIENT_INFO_UNKNOWN : result;
}
/**
* Пытается вытащить реальный IP клиента из WebSocket-сессии.
*
* Приоритет:
* 1) X-Forwarded-For (если стоим за прокси / балансировщиком)
* 2) X-Real-IP
* 3) remoteAddress из WebSocket-сессии
*/
public static String extractClientIp(Session wsSession) {
if (wsSession == null) {
return null;
}
UpgradeRequest req = wsSession.getUpgradeRequest();
// 1) X-Forwarded-For: может быть список IP через запятую
if (req != null) {
String xff = getFirstHeader(req, "X-Forwarded-For");
if (xff != null && !xff.isBlank()) {
String first = xff.split(",")[0].trim();
if (!first.isBlank()) {
return first;
}
}
// 2) X-Real-IP
String xRealIp = getFirstHeader(req, "X-Real-IP");
if (xRealIp != null && !xRealIp.isBlank()) {
return xRealIp.trim();
}
}
// 3) fallback: remoteAddress из WebSocket-сессии
SocketAddress rawAddr = wsSession.getRemoteAddress();
if (rawAddr instanceof InetSocketAddress inet) {
if (inet.getAddress() != null) {
return inet.getAddress().getHostAddress();
}
}
return null;
}
public static String extractPreferredLanguageTag(Session wsSession) {
if (wsSession == null) {
return LANGUAGE_UNKNOWN;
@ -102,5 +143,6 @@ public final class ClientInfoService {
if (sb.length() > 0) {
sb.append("; ");
}
// если строка пустая разделитель не нужен
}
}

View File

@ -15,12 +15,11 @@ import shine.db.dao.ActiveSessionsDAO;
import shine.db.entities.ActiveSession;
import shine.db.entities.SolanaUser;
import shine.geo.ClientInfoService;
import shine.geo.GeoLookupService;
import utils.crypto.Ed25519Util;
import org.eclipse.jetty.websocket.api.Session;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.security.SecureRandom;
@ -178,17 +177,26 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
String clientInfoFromRequest = ClientInfoService.buildClientInfoString(wsSession);
String userLanguage = ClientInfoService.extractPreferredLanguageTag(wsSession);
String clientIp = "";
String clientIp = null;
if (wsSession != null) {
SocketAddress rawAddr = wsSession.getRemoteAddress();
if (rawAddr instanceof InetSocketAddress inet) {
if (inet.getAddress() != null) {
clientIp = inet.getAddress().getHostAddress();
}
}
}
// TODO и сдесь тоже переписываем получение ИП адреса на стандартный метод и тоже дёргаем запрос геолокации который никуда не сохраняем просто что бы он в кэш сервера попал
// стандартный метод получения IP
clientIp = ClientInfoService.extractClientIp(wsSession);
// Дёргаем запрос геолокации (ничего не сохраняем в сессию),
// нужно лишь для того, чтобы данные попали в кэш сервера.
if (clientIp != null && !clientIp.isBlank()) {
try {
GeoLookupService.resolveCountryCityOrIpWithCache(clientIp);
} catch (Exception e) {
// геолокация не критична, можно тихо залогировать на debug
log.debug("Geo lookup failed for ip={}", clientIp, e);
}
}
}
if (clientIp == null) {
clientIp = "";
}
// --- создаём запись ActiveSession и сохраняем в БД ---
ActiveSessionsDAO dao = ActiveSessionsDAO.getInstance();

View File

@ -16,6 +16,7 @@ import shine.db.dao.SolanaUsersDAO;
import shine.db.entities.ActiveSession;
import shine.db.entities.SolanaUser;
import shine.geo.ClientInfoService;
import shine.geo.GeoLookupService;
import java.sql.SQLException;
@ -125,8 +126,20 @@ public class Net_RefreshSession_Handler implements JsonMessageHandler {
String userLanguage = null;
if (ctx != null && ctx.getWsSession() != null) {
clientIp = "8.8.8.8"; //TODO сделать нормальное получение ип адреса
// и сделать запрос геолокации и никуда его не сохранять запрос нужен просто что бы в кэш данные добавилиь если нужно
// Нормальное получение IP-адреса клиента
clientIp = ClientInfoService.extractClientIp(ctx.getWsSession());
// Сделать запрос геолокации и никуда её не сохранять:
// вызов с кэшированием в БД, нужно только для прогрева кэша.
if (clientIp != null && !clientIp.isBlank()) {
try {
GeoLookupService.resolveCountryCityOrIpWithCache(clientIp);
} catch (Exception e) {
// Геолокация не критична, просто логируем на debug/trace при желании
log.debug("Geo lookup failed for ip={}", clientIp, e);
}
}
clientInfoFromRequest = ClientInfoService.buildClientInfoString(ctx.getWsSession());
userLanguage = ClientInfoService.extractPreferredLanguageTag(ctx.getWsSession());
}