SHA256
27 03 25
Доделал сервер и документ для разработчиков по Авторификациии и серверам Всё работает
This commit is contained in:
+145
-36
@@ -10,10 +10,12 @@ import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_CreateAuthSession_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_CreateAuthSession_Response;
|
||||
import server.logic.ws_protocol.JSON.utils.AuthKeyUtils;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import server.logic.ws_protocol.WireCodes;
|
||||
import server.ws.WsConnectionUtils;
|
||||
import shine.db.dao.ActiveSessionsDAO;
|
||||
import shine.db.dao.SolanaUsersDAO;
|
||||
import shine.db.entities.ActiveSessionEntry;
|
||||
import shine.db.entities.SolanaUserEntry;
|
||||
import shine.geo.ClientInfoService;
|
||||
@@ -31,12 +33,12 @@ import java.sql.SQLException;
|
||||
*
|
||||
* Логика авторизации (v2):
|
||||
* - Создание сессии: AuthChallenge(login) -> authNonce -> CreateAuthSession(...)
|
||||
* - Клиент генерирует sessionKey (Ed25519), хранит приватный ключ у себя,
|
||||
* отправляет на сервер ТОЛЬКО sessionPubKeyB64.
|
||||
* - Сервер сохраняет sessionPubKeyB64 в active_sessions.session_key.
|
||||
* - Клиент генерирует sessionKey, хранит приватный ключ у себя,
|
||||
* отправляет на сервер sessionKey целиком одной строкой.
|
||||
* - Сервер сохраняет sessionKey в active_sessions.session_key как есть.
|
||||
*
|
||||
* Подпись deviceKey (Ed25519) проверяется над строкой (UTF-8):
|
||||
* AUTH_CREATE_SESSION:{login}:{timeMs}:{authNonce}
|
||||
* AUTH_CREATE_SESSION:{login}:{sessionKey}:{storagePwd}:{timeMs}:{authNonce}
|
||||
*
|
||||
* На выходе:
|
||||
* - создаётся запись active_sessions
|
||||
@@ -70,8 +72,54 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
return err;
|
||||
}
|
||||
|
||||
SolanaUserEntry user = ctx.getSolanaUser();
|
||||
String login = user.getLogin();
|
||||
SolanaUserEntry userFromContext = ctx.getSolanaUser();
|
||||
String loginFromContext = userFromContext.getLogin();
|
||||
String login = req.getLogin();
|
||||
if (login == null || login.isBlank()) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"EMPTY_LOGIN",
|
||||
"Пустой login"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: empty login");
|
||||
return err;
|
||||
}
|
||||
if (!login.equals(loginFromContext)) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"LOGIN_MISMATCH",
|
||||
"login не соответствует контексту AuthChallenge"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: login mismatch");
|
||||
return err;
|
||||
}
|
||||
|
||||
SolanaUserEntry user;
|
||||
try {
|
||||
user = SolanaUsersDAO.getInstance().getByLogin(login);
|
||||
} catch (SQLException e) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.SERVER_DATA_ERROR,
|
||||
"DB_ERROR_USER_LOOKUP",
|
||||
"Ошибка БД при получении пользователя"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: db user lookup");
|
||||
return err;
|
||||
}
|
||||
if (user == null) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.UNVERIFIED,
|
||||
"USER_NOT_FOUND",
|
||||
"Пользователь не найден"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: user not found");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (login == null || login.isBlank()) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
@@ -95,40 +143,38 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
return err;
|
||||
}
|
||||
|
||||
String sessionPubKeyB64 = req.getSessionPubKeyB64();
|
||||
if (sessionPubKeyB64 == null || sessionPubKeyB64.isBlank()) {
|
||||
String sessionKey = req.getSessionKey();
|
||||
if (sessionKey == null || sessionKey.isBlank()) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"EMPTY_SESSION_PUBKEY",
|
||||
"Пустой sessionPubKeyB64"
|
||||
"EMPTY_SESSION_KEY",
|
||||
"Пустой sessionKey"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: empty session pubkey");
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: empty session key");
|
||||
return err;
|
||||
}
|
||||
|
||||
// Проверим, что sessionPubKeyB64 декодируется в 32 байта
|
||||
byte[] sessionPubKey32;
|
||||
sessionKey = AuthKeyUtils.normalize(sessionKey, "sessionKey");
|
||||
try {
|
||||
sessionPubKey32 = Base64Ws.decode(sessionPubKeyB64);
|
||||
AuthKeyUtils.parseEd25519PublicKey(sessionKey, "sessionKey");
|
||||
} catch (UnsupportedOperationException e) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
422,
|
||||
"UNSUPPORTED_KEY_ALGORITHM",
|
||||
"sessionKey prefix is not supported"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: unsupported session key algorithm");
|
||||
return err;
|
||||
} catch (IllegalArgumentException e) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_BASE64",
|
||||
"Некорректный base64 в sessionPubKeyB64"
|
||||
"Некорректный формат sessionKey"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: bad session pubkey base64");
|
||||
return err;
|
||||
}
|
||||
if (sessionPubKey32.length != 32) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"BAD_SESSION_PUBKEY_LEN",
|
||||
"sessionPubKey должен быть 32 байта"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: bad session pubkey length");
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: bad session key format");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -163,8 +209,8 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
clientInfoFromClient = clientInfoFromClient.substring(0, 50);
|
||||
}
|
||||
|
||||
String devicePubKeyB64 = user.getDeviceKey();
|
||||
if (devicePubKeyB64 == null || devicePubKeyB64.isBlank()) {
|
||||
String deviceKeyFromDb = user.getDeviceKey();
|
||||
if (deviceKeyFromDb == null || deviceKeyFromDb.isBlank()) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
@@ -176,16 +222,73 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
}
|
||||
|
||||
String authNonce = ctx.getAuthNonce();
|
||||
String authNonceFromReq = req.getAuthNonce();
|
||||
if (authNonceFromReq == null || authNonceFromReq.isBlank()) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"EMPTY_AUTH_NONCE",
|
||||
"Пустой authNonce"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: empty authNonce");
|
||||
return err;
|
||||
}
|
||||
if (!authNonce.equals(authNonceFromReq)) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"AUTH_NONCE_MISMATCH",
|
||||
"authNonce не соответствует контексту AuthChallenge"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: authNonce mismatch");
|
||||
return err;
|
||||
}
|
||||
|
||||
String deviceKeyFromReq = req.getDeviceKey();
|
||||
if (deviceKeyFromReq == null || deviceKeyFromReq.isBlank()) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"EMPTY_DEVICE_KEY",
|
||||
"Пустой deviceKey"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: empty deviceKey");
|
||||
return err;
|
||||
}
|
||||
deviceKeyFromReq = deviceKeyFromReq.trim();
|
||||
|
||||
// TODO: для ротации device_key стоит дополнительно сверять актуальное значение через Solana.
|
||||
if (!deviceKeyFromReq.equals(deviceKeyFromDb)) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.UNVERIFIED,
|
||||
"DEVICE_KEY_NOT_ACTUAL",
|
||||
"device_key не соответствует актуальной версии"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: device key mismatch");
|
||||
return err;
|
||||
}
|
||||
|
||||
boolean sigOk;
|
||||
try {
|
||||
sigOk = verifyCreateSessionSignature(
|
||||
user,
|
||||
login,
|
||||
sessionKey,
|
||||
storagePwd,
|
||||
authNonce,
|
||||
timeMs,
|
||||
deviceKeyFromDb,
|
||||
signatureB64
|
||||
);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
422,
|
||||
"UNSUPPORTED_KEY_ALGORITHM",
|
||||
"deviceKey algorithm is not supported"
|
||||
);
|
||||
WsConnectionUtils.closeConnection(ctx, 4001, "Auth failed: unsupported device key algorithm");
|
||||
return err;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Net_Response err = NetExceptionResponseFactory.error(
|
||||
req,
|
||||
@@ -239,7 +342,7 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
activeSessionEntry = new ActiveSessionEntry(
|
||||
sessionId,
|
||||
login,
|
||||
sessionPubKeyB64, // session_key (pubkey)
|
||||
sessionKey, // session_key (pubkey string as-is)
|
||||
storagePwd,
|
||||
now,
|
||||
now,
|
||||
@@ -283,18 +386,24 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
}
|
||||
|
||||
private static boolean verifyCreateSessionSignature(
|
||||
SolanaUserEntry user,
|
||||
String login,
|
||||
String sessionKey,
|
||||
String storagePwd,
|
||||
String authNonce,
|
||||
long timeMs,
|
||||
String deviceKey,
|
||||
String signatureB64
|
||||
) throws IllegalArgumentException {
|
||||
|
||||
// deviceKey (pub, 32)
|
||||
byte[] publicKey32 = Ed25519Util.keyFromBase64(user.getDeviceKey());
|
||||
byte[] signature64 = Base64Ws.decode(signatureB64);
|
||||
byte[] publicKey32 = AuthKeyUtils.parseEd25519PublicKey(deviceKey, "deviceKey");
|
||||
byte[] signature64 = Base64Ws.decodeLen(signatureB64, 64, "signatureB64");
|
||||
|
||||
String preimageStr = "AUTH_CREATE_SESSION:" + login + ":" + timeMs + ":" + authNonce;
|
||||
String preimageStr = "AUTH_CREATE_SESSION:"
|
||||
+ login + ":"
|
||||
+ sessionKey + ":"
|
||||
+ storagePwd + ":"
|
||||
+ timeMs + ":"
|
||||
+ authNonce;
|
||||
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return Ed25519Util.verify(preimage, signature64, publicKey32);
|
||||
@@ -305,4 +414,4 @@ public class Net_CreateAuthSession__Handler implements JsonMessageHandler {
|
||||
RANDOM.nextBytes(buf);
|
||||
return Base64Ws.encode(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
-9
@@ -10,6 +10,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_SessionLogin_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_SessionLogin_Response;
|
||||
import server.logic.ws_protocol.JSON.utils.AuthKeyUtils;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import server.logic.ws_protocol.WireCodes;
|
||||
import shine.db.dao.ActiveSessionsDAO;
|
||||
@@ -30,7 +31,7 @@ import java.sql.SQLException;
|
||||
* - SessionChallenge(sessionId) выдаёт nonce (одноразовый, TTL).
|
||||
* - SessionLogin проверяет подпись sessionKey над строкой:
|
||||
* SESSION_LOGIN:{sessionId}:{timeMs}:{nonce}
|
||||
* - sessionPubKey берём из БД: active_sessions.session_key (base64 32 bytes).
|
||||
* - sessionKey берём из запроса и сверяем с active_sessions.session_key.
|
||||
*
|
||||
* При успехе:
|
||||
* - ctx становится AUTH_STATUS_USER
|
||||
@@ -100,6 +101,17 @@ public class Net_SessionLogin_Handler implements JsonMessageHandler {
|
||||
);
|
||||
}
|
||||
|
||||
String sessionKeyFromReq = req.getSessionKey();
|
||||
if (sessionKeyFromReq == null || sessionKeyFromReq.isBlank()) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.BAD_REQUEST,
|
||||
"EMPTY_SESSION_KEY",
|
||||
"Пустой sessionKey"
|
||||
);
|
||||
}
|
||||
sessionKeyFromReq = AuthKeyUtils.normalize(sessionKeyFromReq, "sessionKey");
|
||||
|
||||
ActiveSessionEntry session;
|
||||
try {
|
||||
session = ActiveSessionsDAO.getInstance().getBySessionId(sessionId);
|
||||
@@ -121,8 +133,8 @@ public class Net_SessionLogin_Handler implements JsonMessageHandler {
|
||||
);
|
||||
}
|
||||
|
||||
String sessionPubKeyB64 = session.getSessionKey(); // это pubKey (Base64(32))
|
||||
if (sessionPubKeyB64 == null || sessionPubKeyB64.isBlank()) {
|
||||
String sessionKeyFromDb = session.getSessionKey();
|
||||
if (sessionKeyFromDb == null || sessionKeyFromDb.isBlank()) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.SERVER_DATA_ERROR,
|
||||
@@ -130,12 +142,29 @@ public class Net_SessionLogin_Handler implements JsonMessageHandler {
|
||||
"В сессии не задан session_key"
|
||||
);
|
||||
}
|
||||
sessionKeyFromDb = sessionKeyFromDb.trim();
|
||||
|
||||
if (!sessionKeyFromReq.equals(sessionKeyFromDb)) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
WireCodes.Status.UNVERIFIED,
|
||||
"SESSION_KEY_NOT_ACTUAL",
|
||||
"session_key не соответствует актуальной версии"
|
||||
);
|
||||
}
|
||||
|
||||
String nonce = ctx.getSessionLoginNonce();
|
||||
|
||||
boolean sigOk;
|
||||
try {
|
||||
sigOk = verifySessionLoginSignature(sessionPubKeyB64, sessionId, timeMs, nonce, signatureB64);
|
||||
sigOk = verifySessionLoginSignature(sessionKeyFromReq, sessionId, timeMs, nonce, signatureB64);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
422,
|
||||
"UNSUPPORTED_KEY_ALGORITHM",
|
||||
"sessionKey prefix is not supported"
|
||||
);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
@@ -243,17 +272,15 @@ public class Net_SessionLogin_Handler implements JsonMessageHandler {
|
||||
}
|
||||
|
||||
private static boolean verifySessionLoginSignature(
|
||||
String sessionPubKeyB64,
|
||||
String sessionKey,
|
||||
String sessionId,
|
||||
long timeMs,
|
||||
String nonce,
|
||||
String signatureB64
|
||||
) throws IllegalArgumentException {
|
||||
|
||||
// pubKey: Base64(32). (Ed25519Util.keyFromBase64 должен использовать стандартный Base64)
|
||||
byte[] publicKey32 = Ed25519Util.keyFromBase64(sessionPubKeyB64);
|
||||
byte[] publicKey32 = AuthKeyUtils.parseEd25519PublicKey(sessionKey, "sessionKey");
|
||||
|
||||
// signature: Base64(64) через единую утилиту WS-протокола
|
||||
byte[] signature64 = Base64Ws.decodeLen(signatureB64, 64, "signatureB64");
|
||||
|
||||
String preimageStr = "SESSION_LOGIN:" + sessionId + ":" + timeMs + ":" + nonce;
|
||||
@@ -261,4 +288,4 @@ public class Net_SessionLogin_Handler implements JsonMessageHandler {
|
||||
|
||||
return Ed25519Util.verify(preimage, signature64, publicKey32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+43
-11
@@ -7,32 +7,48 @@ import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
*
|
||||
* Шаги:
|
||||
* 1) AuthChallenge(login) -> authNonce
|
||||
* 2) CreateAuthSession(storagePwd, sessionPubKeyB64, timeMs, signatureB64, clientInfo)
|
||||
* 2) CreateAuthSession(login, sessionKey, storagePwd, timeMs, authNonce, deviceKey, signatureB64, clientInfo)
|
||||
*
|
||||
* Подпись deviceKey делается над строкой (UTF-8):
|
||||
* AUTH_CREATE_SESSION:{login}:{timeMs}:{authNonce}:{sessionPubKeyB64}:{storagePwd}
|
||||
* AUTH_CREATE_SESSION:{login}:{sessionKey}:{storagePwd}:{timeMs}:{authNonce}
|
||||
*
|
||||
* Важно:
|
||||
* - sessionKey генерируется на клиенте, на сервер отправляется ТОЛЬКО sessionPubKeyB64 (32 bytes base64).
|
||||
* - В БД active_sessions.session_key хранится sessionPubKeyB64.
|
||||
* - sessionKey генерируется на клиенте и передаётся на сервер целиком одной строкой.
|
||||
* - В БД active_sessions.session_key хранится sessionKey целиком одной строкой.
|
||||
*/
|
||||
public class Net_CreateAuthSession_Request extends Net_Request {
|
||||
|
||||
private String login;
|
||||
|
||||
/** Клиентский пароль для хранения данных (base64 от 32 байт). */
|
||||
private String storagePwd;
|
||||
|
||||
/** Публичный ключ сессии (sessionPubKey), base64 от 32 байт. */
|
||||
private String sessionPubKeyB64;
|
||||
/** Публичный ключ сессии в API-формате, например ed25519/BASE64_PUBLIC_KEY. */
|
||||
private String sessionKey;
|
||||
|
||||
/** Время на стороне клиента (мс с 1970-01-01). */
|
||||
private long timeMs;
|
||||
|
||||
/** Nonce из AuthChallenge. */
|
||||
private String authNonce;
|
||||
|
||||
/** Публичный ключ устройства пользователя. */
|
||||
private String deviceKey;
|
||||
|
||||
/** Подпись Ed25519(deviceKey) над строкой AUTH_CREATE_SESSION:... (base64). */
|
||||
private String signatureB64;
|
||||
|
||||
/** Краткая строка от клиента (до 50 символов) с описанием устройства/клиента. */
|
||||
private String clientInfo;
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
public String getStoragePwd() {
|
||||
return storagePwd;
|
||||
}
|
||||
@@ -41,12 +57,12 @@ public class Net_CreateAuthSession_Request extends Net_Request {
|
||||
this.storagePwd = storagePwd;
|
||||
}
|
||||
|
||||
public String getSessionPubKeyB64() {
|
||||
return sessionPubKeyB64;
|
||||
public String getSessionKey() {
|
||||
return sessionKey;
|
||||
}
|
||||
|
||||
public void setSessionPubKeyB64(String sessionPubKeyB64) {
|
||||
this.sessionPubKeyB64 = sessionPubKeyB64;
|
||||
public void setSessionKey(String sessionKey) {
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public long getTimeMs() {
|
||||
@@ -57,6 +73,22 @@ public class Net_CreateAuthSession_Request extends Net_Request {
|
||||
this.timeMs = timeMs;
|
||||
}
|
||||
|
||||
public String getAuthNonce() {
|
||||
return authNonce;
|
||||
}
|
||||
|
||||
public void setAuthNonce(String authNonce) {
|
||||
this.authNonce = authNonce;
|
||||
}
|
||||
|
||||
public String getDeviceKey() {
|
||||
return deviceKey;
|
||||
}
|
||||
|
||||
public void setDeviceKey(String deviceKey) {
|
||||
this.deviceKey = deviceKey;
|
||||
}
|
||||
|
||||
public String getSignatureB64() {
|
||||
return signatureB64;
|
||||
}
|
||||
@@ -72,4 +104,4 @@ public class Net_CreateAuthSession_Request extends Net_Request {
|
||||
public void setClientInfo(String clientInfo) {
|
||||
this.clientInfo = clientInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -4,7 +4,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
|
||||
/**
|
||||
* Шаг 2 входа в существующую сессию (v2):
|
||||
* SessionLogin(sessionId, timeMs, signatureB64) -> storagePwd, AUTH_STATUS_USER
|
||||
* SessionLogin(sessionId, sessionKey, timeMs, signatureB64) -> storagePwd, AUTH_STATUS_USER
|
||||
*
|
||||
* Подпись делается sessionKey (приватный ключ на устройстве) над строкой (UTF-8):
|
||||
* SESSION_LOGIN:{sessionId}:{timeMs}:{nonce}
|
||||
@@ -14,6 +14,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
public class Net_SessionLogin_Request extends Net_Request {
|
||||
|
||||
private String sessionId;
|
||||
private String sessionKey;
|
||||
private long timeMs;
|
||||
private String signatureB64;
|
||||
|
||||
@@ -28,6 +29,14 @@ public class Net_SessionLogin_Request extends Net_Request {
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
public String getSessionKey() {
|
||||
return sessionKey;
|
||||
}
|
||||
|
||||
public void setSessionKey(String sessionKey) {
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public long getTimeMs() {
|
||||
return timeMs;
|
||||
}
|
||||
@@ -51,4 +60,4 @@ public class Net_SessionLogin_Request extends Net_Request {
|
||||
public void setClientInfo(String clientInfo) {
|
||||
this.clientInfo = clientInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user