11 12 25
Добавил поле authNonce(Вместо SessionPWD) при запросе авторизации
This commit is contained in:
parent
dbf1f22bac
commit
80ffba545a
@ -27,11 +27,16 @@ public class ConnectionContext {
|
|||||||
private String sessionId;
|
private String sessionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Временный секрет шага 1, который используется на шаге 2 и хранится в БД,
|
* Секрет сессии (то, что хранится в active_sessions.session_pwd).
|
||||||
* а после успешной авторизации — настоящий секрет сессии.
|
|
||||||
*/
|
*/
|
||||||
private String sessionPwd;
|
private String sessionPwd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Одноразовый nonce, выданный на шаге 1 (AuthChallenge),
|
||||||
|
* используется на шаге 2 для проверки подписи.
|
||||||
|
*/
|
||||||
|
private String authNonce;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Текущий статус аутентификации.
|
* Текущий статус аутентификации.
|
||||||
* См. константы AUTH_STATUS_*
|
* См. константы AUTH_STATUS_*
|
||||||
@ -100,6 +105,16 @@ public class ConnectionContext {
|
|||||||
this.sessionPwd = sessionPwd;
|
this.sessionPwd = sessionPwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- authNonce ---
|
||||||
|
|
||||||
|
public String getAuthNonce() {
|
||||||
|
return authNonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthNonce(String authNonce) {
|
||||||
|
this.authNonce = authNonce;
|
||||||
|
}
|
||||||
|
|
||||||
// --- auth status ---
|
// --- auth status ---
|
||||||
|
|
||||||
public int getAuthenticationStatus() {
|
public int getAuthenticationStatus() {
|
||||||
@ -124,6 +139,7 @@ public class ConnectionContext {
|
|||||||
|
|
||||||
sessionId = null;
|
sessionId = null;
|
||||||
sessionPwd = null;
|
sessionPwd = null;
|
||||||
|
authNonce = null;
|
||||||
|
|
||||||
authenticationStatus = AUTH_STATUS_NONE;
|
authenticationStatus = AUTH_STATUS_NONE;
|
||||||
wsSession = null;
|
wsSession = null;
|
||||||
|
|||||||
@ -3,9 +3,9 @@ package server.logic.ws_protocol.JSON.entyties.Auth;
|
|||||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Шаг 1 авторизации: запрос выдачи временного пароля сессии (sessionPwd).
|
* Шаг 1 авторизации: запрос выдачи одноразового nonce (authNonce).
|
||||||
*
|
*
|
||||||
* Клиент по логину просит сервер сгенерировать случайный секрет sessionPwd,
|
* Клиент по логину просит сервер сгенерировать случайный authNonce,
|
||||||
* который будет использован на втором шаге при подписи.
|
* который будет использован на втором шаге при подписи.
|
||||||
*
|
*
|
||||||
* Формат входящего JSON:
|
* Формат входящего JSON:
|
||||||
@ -23,7 +23,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
|||||||
* "requestId": "...",
|
* "requestId": "...",
|
||||||
* "status": 200,
|
* "status": 200,
|
||||||
* "payload": {
|
* "payload": {
|
||||||
* "sessionPwd": "base64-строка-от-32-байт"
|
* "authNonce": "base64-строка-от-32-байт"
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -71,8 +71,8 @@ public class Net_AuthChallenge_Handler implements JsonMessageHandler {
|
|||||||
RANDOM.nextBytes(buf);
|
RANDOM.nextBytes(buf);
|
||||||
String authNonce = Base64.getUrlEncoder().withoutPadding().encodeToString(buf);
|
String authNonce = Base64.getUrlEncoder().withoutPadding().encodeToString(buf);
|
||||||
|
|
||||||
// Используем поле sessionPwd в контексте как хранилище challenge (authNonce) до шага 2
|
// Сохраняем challenge в отдельном поле authNonce
|
||||||
ctx.setSessionPwd(authNonce);
|
ctx.setAuthNonce(authNonce);
|
||||||
|
|
||||||
// 5) Формируем ответ
|
// 5) Формируем ответ
|
||||||
Net_AuthChallenge_Response resp = new Net_AuthChallenge_Response();
|
Net_AuthChallenge_Response resp = new Net_AuthChallenge_Response();
|
||||||
|
|||||||
@ -35,7 +35,8 @@ import java.util.Base64;
|
|||||||
* "AUTHORIFICATED:" + timeMs + authNonce)
|
* "AUTHORIFICATED:" + timeMs + authNonce)
|
||||||
* - clientInfo (опционально, до 50 символов)
|
* - clientInfo (опционально, до 50 символов)
|
||||||
*
|
*
|
||||||
* authNonce клиент получил на шаге 1 (AuthChallenge).
|
* authNonce клиент получил на шаге 1 (AuthChallenge) и сервер
|
||||||
|
* сохранил его в ctx.authNonce.
|
||||||
*
|
*
|
||||||
* При успехе:
|
* При успехе:
|
||||||
* - создаётся запись ActiveSession в БД;
|
* - создаётся запись ActiveSession в БД;
|
||||||
@ -59,27 +60,19 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
|||||||
public Net_Response handle(Net_Request baseReq, ConnectionContext ctx) throws Exception {
|
public Net_Response handle(Net_Request baseReq, ConnectionContext ctx) throws Exception {
|
||||||
Net_CreateAuthSession_Request req = (Net_CreateAuthSession_Request) baseReq;
|
Net_CreateAuthSession_Request req = (Net_CreateAuthSession_Request) baseReq;
|
||||||
|
|
||||||
// --- базовые проверки контекста ---
|
// --- базовые проверки контекста шага 1 ---
|
||||||
if (ctx == null || ctx.getSolanaUser() == null || ctx.getSessionPwd() == null) {
|
if (ctx == null
|
||||||
|
|| ctx.getSolanaUser() == null
|
||||||
|
|| ctx.getAuthNonce() == null
|
||||||
|
|| ctx.getAuthenticationStatus() != ConnectionContext.AUTH_STATUS_AUTH_IN_PROGRESS) {
|
||||||
|
|
||||||
Net_Response err = NetExceptionResponseFactory.error(
|
Net_Response err = NetExceptionResponseFactory.error(
|
||||||
req,
|
req,
|
||||||
WireCodes.Status.BAD_REQUEST,
|
WireCodes.Status.BAD_REQUEST,
|
||||||
"NO_STEP1_CONTEXT",
|
"NO_STEP1_CONTEXT",
|
||||||
"Шаг 1 авторизации не был корректно выполнен для данного соединения"
|
"Шаг 1 авторизации не был корректно выполнен для данного соединения"
|
||||||
);
|
);
|
||||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: no step1 context");
|
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: no step1 context or bad auth state");
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ожидаем, что перед этим был AuthChallenge и статус = AUTH_IN_PROGRESS
|
|
||||||
if (ctx.getAuthenticationStatus() != ConnectionContext.AUTH_STATUS_AUTH_IN_PROGRESS) {
|
|
||||||
Net_Response err = NetExceptionResponseFactory.error(
|
|
||||||
req,
|
|
||||||
WireCodes.Status.BAD_REQUEST,
|
|
||||||
"BAD_AUTH_FLOW_STATE",
|
|
||||||
"Неожиданное состояние авторификации для данного соединения"
|
|
||||||
);
|
|
||||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: bad auth flow state");
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,8 +163,8 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- authNonce (challenge) мы сохранили в ctx.sessionPwd на шаге 1 ---
|
// --- authNonce (challenge) мы сохранили в ctx.authNonce на шаге 1 ---
|
||||||
String authNonce = ctx.getSessionPwd();
|
String authNonce = ctx.getAuthNonce();
|
||||||
|
|
||||||
// --- собираем строку для подписи: "AUTHORIFICATED:" + timeMs + authNonce ---
|
// --- собираем строку для подписи: "AUTHORIFICATED:" + timeMs + authNonce ---
|
||||||
String preimageStr = "AUTHORIFICATED:" + timeMs + authNonce;
|
String preimageStr = "AUTHORIFICATED:" + timeMs + authNonce;
|
||||||
@ -201,16 +194,12 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
|||||||
|
|
||||||
String clientIp = null;
|
String clientIp = null;
|
||||||
if (wsSession != null) {
|
if (wsSession != null) {
|
||||||
// стандартный метод получения IP
|
|
||||||
clientIp = ClientInfoService.extractClientIp(wsSession);
|
clientIp = ClientInfoService.extractClientIp(wsSession);
|
||||||
|
|
||||||
// Дёргаем запрос геолокации (ничего не сохраняем в сессию),
|
|
||||||
// нужно лишь для того, чтобы данные попали в кэш сервера.
|
|
||||||
if (clientIp != null && !clientIp.isBlank()) {
|
if (clientIp != null && !clientIp.isBlank()) {
|
||||||
try {
|
try {
|
||||||
GeoLookupService.resolveCountryCityOrIpWithCache(clientIp);
|
GeoLookupService.resolveCountryCityOrIpWithCache(clientIp);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// геолокация не критична, можно тихо залогировать на debug
|
|
||||||
log.debug("Geo lookup failed for ip={}", clientIp, e);
|
log.debug("Geo lookup failed for ip={}", clientIp, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +246,8 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
|||||||
// --- обновляем контекст ---
|
// --- обновляем контекст ---
|
||||||
ctx.setActiveSession(activeSession);
|
ctx.setActiveSession(activeSession);
|
||||||
ctx.setSessionId(sessionId);
|
ctx.setSessionId(sessionId);
|
||||||
ctx.setSessionPwd(newSessionPwd); // теперь в контексте хранится секрет сессии, а не authNonce
|
ctx.setSessionPwd(newSessionPwd); // теперь в контексте хранится секрет сессии
|
||||||
|
ctx.setAuthNonce(null); // одноразовый nonce больше не нужен
|
||||||
ctx.setAuthenticationStatus(ConnectionContext.AUTH_STATUS_USER);
|
ctx.setAuthenticationStatus(ConnectionContext.AUTH_STATUS_USER);
|
||||||
|
|
||||||
ActiveConnectionsRegistry.getInstance().register(ctx);
|
ActiveConnectionsRegistry.getInstance().register(ctx);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user