修复验证码发送递归重复问题

This commit is contained in:
2026-01-16 13:05:59 +08:00
parent 9863e77512
commit 47fce9bc19
9 changed files with 131 additions and 76995 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
bin/
logs/
runtime/
config.ini
*.log

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
#!/bin/bash
# Termux专属启动脚本 编译+启动 解决exit后卡空行/需手动^C问题
# 优化增加JVM内存限制、进程异常捕获、日志输出
cd "$(dirname "${BASH_SOURCE[0]}")" || { echo "目录切换失败"; exit 1; }
BASE_DIR=$(cd .. && pwd)
@@ -12,12 +13,28 @@ CLASSPATH="$BASE_DIR/runtime"
[ -d "$BASE_DIR/libs" ] && CLASSPATH="$CLASSPATH:$BASE_DIR/libs/*"
MAIN_CLASS="Main"
# 3. 关键修复:预重置终端+进程绑定+退出后强制清流
# 3. 关键优化JVM内存限制避免内存耗尽+ 异常日志输出
export _JAVA_OPTIONS="-Xmx128m -Xms64m" # 限制最大堆内存128M初始堆64M适配Termux
STOP_SIGNAL=0
# 捕获进程异常终止信号
on_exit() {
STOP_SIGNAL=1
echo -e "\n⚠ 服务异常终止,可查看日志排查问题"
stty sane
exit 1
}
trap 'on_exit' SIGABRT SIGSEGV SIGILL SIGTERM
# 4. 启动服务+日志输出
stty -echoctl # 屏蔽^C视觉印记
echo -e "\n🚀 服务启动中输入help查指令输入exit优雅停机"
# 启动并绑定进程Java结束脚本立刻走后续逻辑
java -cp "$CLASSPATH" "$MAIN_CLASS"
# Java退出后 强制重置终端+脚本退出,彻底无残留
java -cp "$CLASSPATH" "$MAIN_CLASS" 2> "$BASE_DIR/logs/error.log" # 异常日志写入文件
# 5. Java退出后 强制重置终端+脚本退出,彻底无残留
if [ $STOP_SIGNAL -eq 0 ]; then
echo -e "\n✅ 服务优雅停机"
fi
stty sane
exit $?

View File

@@ -1,12 +1,12 @@
import cc.winboll.LogUtils;
import cc.winboll.auth.AuthCenterHttpService;
import cc.winboll.auth.MailAuthUtils;
import cc.winboll.service.AuthCenterHttpService;
import cc.winboll.util.ConsoleInputUtils;
import cc.winboll.util.EmailSendUtils;
import cc.winboll.util.EnvInfoUtils;
import cc.winboll.util.IniConfigUtils;
import cc.winboll.util.ServerUtils;
import cc.winboll.util.InitCheckUtils;
import cc.winboll.util.EmailSendUtils;
import cc.winboll.util.ServerUtils;
import java.io.IOException;
/**

View File

@@ -1,4 +1,4 @@
package cc.winboll.auth;
package cc.winboll.service;
import cc.winboll.LogUtils;
import cc.winboll.util.ServerUtils;
@@ -71,7 +71,7 @@ public class AuthCenterHttpService extends NanoHTTPD {
} catch (Exception e) {
LogUtils.e(TAG, "请求处理异常", e);
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "application/json",
"{\"code\":500,\"msg\":\"服务内部异常\",\"data\":null}");
"{\"code\":500,\"msg\":\"服务内部异常\",\"data\":null}");
}
}
@@ -79,18 +79,26 @@ public class AuthCenterHttpService extends NanoHTTPD {
private Response handlePingRequest() {
LogUtils.d(TAG, "ping请求响应成功返回pong");
return newFixedLengthResponse(Response.Status.OK, "application/json",
"{\"code\":200,\"msg\":\"pong\",\"data\":null}");
"{\"code\":200,\"msg\":\"pong\",\"data\":null}");
}
// 发送验证码直接调用ServerUtils
// 发送验证码修改为调用本地方法解决递归问题
private Response handleSendVerifyCode(IHTTPSession session) throws IOException, NanoHTTPD.ResponseException{
session.parseBody(null);
Map<String, String> params = session.getParms();
String email = params.get("email");
LogUtils.d(TAG, "接收验证码发送请求,邮箱:" + email);
String result = ServerUtils.sendVerifyCode(email);
return newFixedLengthResponse(Response.Status.OK, "application/json", result);
// 核心修改替换为本地发送方法返回布尔值
boolean sendResult = ServerUtils.sendVerifyCodeLocal(email);
// 统一返回JSON格式与其他接口保持一致
String responseJson;
if (sendResult) {
responseJson = "{\"code\":200,\"msg\":\"验证码发送成功\",\"data\":null}";
} else {
responseJson = "{\"code\":500,\"msg\":\"验证码发送失败\",\"data\":null}";
}
return newFixedLengthResponse(Response.Status.OK, "application/json", responseJson);
}
// 校验验证码直接调用ServerUtils
@@ -102,6 +110,10 @@ public class AuthCenterHttpService extends NanoHTTPD {
LogUtils.d(TAG, "接收验证码校验请求,邮箱:" + email + ",验证码:" + code);
String result = ServerUtils.verifyCode(email, code);
// 兜底处理null值避免返回空响应
if (result == null) {
result = "{\"code\":500,\"msg\":\"校验失败\",\"data\":null}";
}
return newFixedLengthResponse(Response.Status.OK, "application/json", result);
}
@@ -114,6 +126,9 @@ public class AuthCenterHttpService extends NanoHTTPD {
LogUtils.d(TAG, "接收公钥提交请求,邮箱:" + email + ",公钥:" + publicKey);
String result = ServerUtils.submitAppPublicKey(email, publicKey);
if (result == null) {
result = "{\"code\":500,\"msg\":\"公钥提交失败\",\"data\":null}";
}
return newFixedLengthResponse(Response.Status.OK, "application/json", result);
}
@@ -125,6 +140,9 @@ public class AuthCenterHttpService extends NanoHTTPD {
LogUtils.d(TAG, "接收心跳请求,加密数据:" + encryptData);
String result = ServerUtils.sendPingRequest(encryptData);
if (result == null) {
result = "{\"code\":500,\"msg\":\"心跳请求失败\",\"data\":null}";
}
return newFixedLengthResponse(Response.Status.OK, "application/json", result);
}

View File

@@ -13,10 +13,10 @@ import java.util.Map;
/**
* 纯服务器交互工具类仅负责封装HTTP请求、调用远程接口无监听能力
* 适配Java7语法兼容Android API30环境新增服务器连通性一键测试
* 适配Java7语法兼容Android API30环境新增服务器连通性一键测试 + 本地验证码发送能力
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Date 2026/01/16 00:00:00
* @LastEditTime 2026/01/17 16:00:00
* @LastEditTime 2026/01/18 10:00:00
*/
public class ServerUtils {
// 基础属性
@@ -39,18 +39,44 @@ public class ServerUtils {
}
/**
* 优化版发送验证码请求POST增强校验+兜底提示
* ===================== 新增核心本地发送验证码供HTTP服务内部调用无递归 =====================
* 直接调用EmailSendUtils不发起HTTP请求彻底解决递归问题
*/
public static boolean sendVerifyCodeLocal(String email) {
LogUtils.d(TAG, "调用sendVerifyCodeLocal本地发送验证码邮箱" + email);
// 1. 前置校验:邮箱格式
if (email == null || email.trim().isEmpty() || !email.contains("@")) {
LogUtils.w(TAG, "本地发送验证码失败:邮箱为空或格式不合法");
return false;
}
String trimEmail = email.trim();
// 2. 生成6位验证码依赖VerifyCodeUtils需确保该类存在
String verifyCode = VerifyCodeUtils.generateCode();
// 3. 直接调用邮件工具类发送
boolean sendResult = EmailSendUtils.sendVerifyCodeEmail(trimEmail, verifyCode);
// 4. 缓存验证码供后续校验依赖VerifyCodeCacheUtils
if (sendResult) {
VerifyCodeCacheUtils.putCode(trimEmail, verifyCode);
LogUtils.i(TAG, "本地验证码发送成功,邮箱[" + trimEmail + "] 验证码[" + verifyCode + "]");
} else {
LogUtils.e(TAG, "本地验证码发送失败,邮箱[" + trimEmail + "]");
}
return sendResult;
}
/**
* 优化版发送验证码请求POST供外部客户端调用远程接口保留原逻辑
*/
public static String sendVerifyCode(String email) {
LogUtils.d(TAG, "调用sendVerifyCode邮箱参数" + email);
LogUtils.d(TAG, "调用sendVerifyCode远程请求验证码,邮箱参数:" + email);
// 1. 前置校验:服务器地址未初始化
if (serverBaseUrl == null || serverBaseUrl.trim().isEmpty()) {
LogUtils.e(TAG, "发送验证码失败服务器地址未初始化请先调用initServerUrl()");
LogUtils.e(TAG, "远程发送验证码失败服务器地址未初始化请先调用initServerUrl()");
return null;
}
// 2. 前置校验:邮箱空值/格式基础校验
if (email == null || email.trim().isEmpty() || !email.contains("@")) {
LogUtils.w(TAG, "发送验证码失败:邮箱地址为空或格式不合法");
LogUtils.w(TAG, "远程发送验证码失败:邮箱地址为空或格式不合法");
return null;
}
String trimEmail = email.trim();
@@ -58,7 +84,7 @@ public class ServerUtils {
Map<String, String> params = new HashMap<String, String>();
params.put("email", trimEmail);
String result = sendPostRequest(url, params);
LogUtils.d(TAG, "验证码发送请求执行完成,邮箱[" + trimEmail + "] 接口响应:" + (result == null ? "null" : result));
LogUtils.d(TAG, "远程验证码请求执行完成,邮箱[" + trimEmail + "] 接口响应:" + (result == null ? "null" : result));
return result;
}

View File

@@ -0,0 +1,32 @@
package cc.winboll.util;
import java.util.HashMap;
import java.util.Map;
/**
* 验证码缓存工具类适配Java7临时存储验证码用于校验
*/
public class VerifyCodeCacheUtils {
private static final Map<String, String> CODE_CACHE = new HashMap<>();
/**
* 存入验证码,键为邮箱
*/
public static void putCode(String email, String code) {
CODE_CACHE.put(email, code);
}
/**
* 获取验证码,键为邮箱
*/
public static String getCode(String email) {
return CODE_CACHE.get(email);
}
/**
* 移除已校验的验证码,释放内存
*/
public static void removeCode(String email) {
CODE_CACHE.remove(email);
}
}

View File

@@ -0,0 +1,16 @@
package cc.winboll.util;
import java.util.Random;
/**
* 验证码生成工具类适配Java7
*/
public class VerifyCodeUtils {
/**
* 生成6位纯数字验证码
*/
public static String generateCode() {
Random random = new Random();
return String.format("%06d", random.nextInt(999999));
}
}