Skip to content

Commit bba906a

Browse files
feat(user-api): 将异步令牌生成与验证改为同步等待结果
将 UserApiController 中的令牌生成和验证逻辑从异步回调模式修改为同步阻塞模式, 通过 `.get()` 方法等待 CompletableFuture 的执行结果。同时增加对 InterruptedException 和 ExecutionException 的捕获处理,提升错误处理的准确性与完整性。 此外,优化了用户注册流程中的白名单添加及令牌标记逻辑,确保各步骤按顺序同步执行, 避免因异步导致的状态不一致问题。 还调整了 whitelist 表结构,允许 uuid 字段为空,并新增 uuid_pending 字段用于标识 UUID 是否待补充,以支持首次登录时自动填充 UUID 的场景。
1 parent 642d638 commit bba906a

2 files changed

Lines changed: 81 additions & 87 deletions

File tree

src/main/java/com/xaoxiao/convenientaccess/api/UserApiController.java

Lines changed: 79 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -87,26 +87,29 @@ public void handleGenerateToken(HttpServletRequest request, HttpServletResponse
8787

8888
final int finalExpiryHours = expiryHours; // 为lambda表达式创建final变量
8989

90-
// 生成注册令牌
91-
tokenManager.generateRegistrationToken(finalExpiryHours)
92-
.thenAccept(token -> {
93-
if (token != null) {
94-
JsonObject responseData = new JsonObject();
95-
responseData.addProperty("token", token);
96-
responseData.addProperty("expiryHours", finalExpiryHours);
97-
responseData.addProperty("message", "令牌生成成功");
98-
99-
sendJsonResponse(response, 200, ApiResponse.success(responseData, "令牌生成成功"));
100-
logger.info("管理员生成注册令牌成功,过期时间: {}小时", finalExpiryHours);
101-
} else {
102-
sendJsonResponse(response, 500, ApiResponse.error("令牌生成失败"));
103-
}
104-
})
105-
.exceptionally(throwable -> {
106-
logger.error("生成注册令牌失败", throwable);
107-
sendJsonResponse(response, 500, ApiResponse.error("令牌生成服务异常"));
108-
return null;
109-
});
90+
// 生成注册令牌(同步等待结果)
91+
try {
92+
String token = tokenManager.generateRegistrationToken(finalExpiryHours).get();
93+
94+
if (token != null) {
95+
JsonObject responseData = new JsonObject();
96+
responseData.addProperty("token", token);
97+
responseData.addProperty("expiryHours", finalExpiryHours);
98+
responseData.addProperty("message", "令牌生成成功");
99+
100+
sendJsonResponse(response, 200, ApiResponse.success(responseData, "令牌生成成功"));
101+
logger.info("管理员生成注册令牌成功,过期时间: {}小时", finalExpiryHours);
102+
} else {
103+
sendJsonResponse(response, 500, ApiResponse.error("令牌生成失败"));
104+
}
105+
} catch (InterruptedException e) {
106+
Thread.currentThread().interrupt();
107+
logger.error("生成注册令牌被中断", e);
108+
sendJsonResponse(response, 500, ApiResponse.error("令牌生成被中断"));
109+
} catch (java.util.concurrent.ExecutionException e) {
110+
logger.error("生成注册令牌失败", e);
111+
sendJsonResponse(response, 500, ApiResponse.error("令牌生成服务异常: " + e.getMessage()));
112+
}
110113

111114
} catch (Exception e) {
112115
logger.error("处理令牌生成请求失败", e);
@@ -150,73 +153,63 @@ public void handleRegister(HttpServletRequest request, HttpServletResponse respo
150153
return;
151154
}
152155

153-
// 验证注册令牌
154-
tokenManager.validateToken(token, clientIp)
155-
.thenAccept(validationResult -> {
156-
if (!validationResult.isValid()) {
157-
sendJsonResponse(response, 400, ApiResponse.badRequest(validationResult.getMessage()));
158-
return;
156+
// 验证注册令牌(同步等待结果)
157+
try {
158+
var validationResult = tokenManager.validateToken(token, clientIp).get();
159+
160+
if (!validationResult.isValid()) {
161+
sendJsonResponse(response, 400, ApiResponse.badRequest(validationResult.getMessage()));
162+
return;
163+
}
164+
165+
// 检查玩家是否已在白名单中
166+
boolean isWhitelisted = whitelistManager.isPlayerWhitelisted(playerUuid).get();
167+
if (isWhitelisted) {
168+
sendJsonResponse(response, 409, ApiResponse.error("玩家已在白名单中"));
169+
return;
170+
}
171+
172+
// 添加玩家到白名单
173+
boolean addSuccess = whitelistManager.addPlayer(
174+
playerName,
175+
playerUuid,
176+
"SYSTEM",
177+
"00000000-0000-0000-0000-000000000000",
178+
WhitelistEntry.Source.SYSTEM
179+
).get();
180+
181+
if (!addSuccess) {
182+
sendJsonResponse(response, 500, ApiResponse.error("添加到白名单失败"));
183+
return;
184+
}
185+
186+
// 标记令牌为已使用
187+
try {
188+
boolean markSuccess = tokenManager.markTokenAsUsed(validationResult.getTokenId(), clientIp).get();
189+
if (!markSuccess) {
190+
logger.warn("标记令牌为已使用失败,但玩家已添加到白名单");
159191
}
160-
161-
// 检查玩家是否已在白名单中
162-
whitelistManager.isPlayerWhitelisted(playerUuid)
163-
.thenAccept(isWhitelisted -> {
164-
if (isWhitelisted) {
165-
sendJsonResponse(response, 409, ApiResponse.error("玩家已在白名单中"));
166-
return;
167-
}
168-
169-
// 添加玩家到白名单
170-
whitelistManager.addPlayer(
171-
playerName,
172-
playerUuid,
173-
"SYSTEM",
174-
"00000000-0000-0000-0000-000000000000",
175-
WhitelistEntry.Source.SYSTEM
176-
).thenAccept(addSuccess -> {
177-
if (addSuccess) {
178-
// 标记令牌为已使用
179-
tokenManager.markTokenAsUsed(validationResult.getTokenId(), clientIp)
180-
.thenAccept(markSuccess -> {
181-
if (markSuccess) {
182-
JsonObject responseData = new JsonObject();
183-
responseData.addProperty("playerName", playerName);
184-
responseData.addProperty("playerUuid", playerUuid);
185-
responseData.addProperty("message", "注册成功,已添加到白名单");
186-
187-
sendJsonResponse(response, 200, ApiResponse.success(responseData, "注册成功"));
188-
logger.info("用户注册成功: {} ({})", playerName, playerUuid);
189-
} else {
190-
logger.error("标记令牌为已使用失败,但玩家已添加到白名单");
191-
sendJsonResponse(response, 200, ApiResponse.success(null, "注册成功(令牌状态更新异常)"));
192-
}
193-
})
194-
.exceptionally(throwable -> {
195-
logger.error("标记令牌为已使用失败", throwable);
196-
sendJsonResponse(response, 200, ApiResponse.success(null, "注册成功(令牌状态更新异常)"));
197-
return null;
198-
});
199-
} else {
200-
sendJsonResponse(response, 500, ApiResponse.error("添加到白名单失败"));
201-
}
202-
})
203-
.exceptionally(throwable -> {
204-
logger.error("添加玩家到白名单失败", throwable);
205-
sendJsonResponse(response, 500, ApiResponse.error("白名单服务异常"));
206-
return null;
207-
});
208-
})
209-
.exceptionally(throwable -> {
210-
logger.error("检查玩家白名单状态失败", throwable);
211-
sendJsonResponse(response, 500, ApiResponse.error("白名单查询服务异常"));
212-
return null;
213-
});
214-
})
215-
.exceptionally(throwable -> {
216-
logger.error("验证注册令牌失败", throwable);
217-
sendJsonResponse(response, 500, ApiResponse.error("令牌验证服务异常"));
218-
return null;
219-
});
192+
} catch (Exception e) {
193+
logger.error("标记令牌为已使用失败", e);
194+
}
195+
196+
// 发送成功响应
197+
JsonObject responseData = new JsonObject();
198+
responseData.addProperty("playerName", playerName);
199+
responseData.addProperty("playerUuid", playerUuid);
200+
responseData.addProperty("message", "注册成功,已添加到白名单");
201+
202+
sendJsonResponse(response, 200, ApiResponse.success(responseData, "注册成功"));
203+
logger.info("用户注册成功: {} ({})", playerName, playerUuid);
204+
205+
} catch (InterruptedException e) {
206+
Thread.currentThread().interrupt();
207+
logger.error("用户注册被中断", e);
208+
sendJsonResponse(response, 500, ApiResponse.error("注册被中断"));
209+
} catch (java.util.concurrent.ExecutionException e) {
210+
logger.error("用户注册失败", e);
211+
sendJsonResponse(response, 500, ApiResponse.error("注册服务异常: " + e.getMessage()));
212+
}
220213

221214
} catch (Exception e) {
222215
logger.error("处理用户注册请求失败", e);

src/main/resources/schema/whitelist.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
CREATE TABLE IF NOT EXISTS whitelist (
33
id INTEGER PRIMARY KEY AUTOINCREMENT,
44
name VARCHAR(16) NOT NULL, -- 玩家名称
5-
uuid VARCHAR(36) NOT NULL UNIQUE, -- 玩家UUID (唯一)
5+
uuid VARCHAR(36) UNIQUE, -- 玩家UUID (唯一,允许为空,首次登录时自动补充)
66
added_by_name VARCHAR(16) NOT NULL, -- 添加者名称
77
added_by_uuid VARCHAR(36) NOT NULL, -- 添加者UUID
88
added_at TIMESTAMP NOT NULL, -- 添加时间 (插件格式)
99
source VARCHAR(10) NOT NULL DEFAULT 'PLAYER', -- 来源类型
1010
is_active BOOLEAN NOT NULL DEFAULT 1, -- 是否激活
11+
uuid_pending BOOLEAN NOT NULL DEFAULT 0, -- UUID是否待补充
1112
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1213
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1314

0 commit comments

Comments
 (0)