feat/vtk-3d-view #7
|
|
@ -16,7 +16,7 @@ namespace {
|
|||
constexpr int kCodeSuccess = 200;
|
||||
|
||||
const char* const kPathImageCode = "/business/system/personalUser/getImageCode";
|
||||
const char* const kPathVerifyCode = "/business/system/personalUser/verifyCodeCheck";
|
||||
// 原版实测(Playwright):登录只 getImageCode → login2 直连,无 verifyCodeCheck(多调会消费验证码→过期)。
|
||||
const char* const kPathLogin = "/admin/tenant/auth/login2";
|
||||
|
||||
} // namespace
|
||||
|
|
@ -34,24 +34,19 @@ LoginLoad* AuthService::loginAsync(const QString& username, const QString& passw
|
|||
// 失败判定与同步版一致:服务端 code != 200 或存在传输层 rawError。
|
||||
auto isFailure = [](const ApiResponse& r) { return r.code != kCodeSuccess || !r.rawError.isEmpty(); };
|
||||
|
||||
// step1:校验验证码(与 captcha 同会话)。
|
||||
ApiChain::StepFactory step1 = [this, code, codeId](const QList<ApiResponse>&) -> IApiCall* {
|
||||
const QJsonObject body{{QStringLiteral("code"), code}, {QStringLiteral("codeId"), codeId}};
|
||||
return api_.postJsonAsync(QString::fromLatin1(kPathVerifyCode), body);
|
||||
};
|
||||
|
||||
// step2:RSA 加密密码(PKCS#1 v1.5 -> base64,可抛 std::exception → ApiChain 转 failed)-> login2。
|
||||
ApiChain::StepFactory step2 = [this, username, password, code, codeId](const QList<ApiResponse>&) -> IApiCall* {
|
||||
// 唯一步:RSA 加密密码(PKCS#1 v1.5 -> base64,可抛 std::exception → ApiChain 转 failed)→ login2,
|
||||
// body 直接带 checkCode(用户输入验证码)+ codeId(验证码会话)。无 verifyCodeCheck 前置(原版实测)。
|
||||
ApiChain::StepFactory step = [this, username, password, code, codeId](const QList<ApiResponse>&) -> IApiCall* {
|
||||
RsaEncryptor enc(rsaPublicKeyPem_);
|
||||
const std::string encrypted = enc.encryptBase64(password.toStdString());
|
||||
const QJsonObject body{{QStringLiteral("username"), username},
|
||||
{QStringLiteral("password"), QString::fromStdString(encrypted)},
|
||||
{QStringLiteral("checkCode"), code}, // 用户输入的验证码(后端 checkCodeNotNull)
|
||||
{QStringLiteral("checkCode"), code},
|
||||
{QStringLiteral("codeId"), codeId}};
|
||||
return api_.postJsonAsync(QString::fromLatin1(kPathLogin), body);
|
||||
};
|
||||
|
||||
auto* chain = new ApiChain({step1, step2}, isFailure);
|
||||
auto* chain = new ApiChain({step}, isFailure);
|
||||
return new LoginLoad(chain);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@ TEST(AuthLiveTest, FullLoginFlowReturnsToken) {
|
|||
<< (capFail.count() ? capFail.takeFirst().at(0).toString().toStdString() : "captcha failed");
|
||||
auto cap = capDone.takeFirst().at(0).value<geopro::net::AuthService::Captcha>();
|
||||
ASSERT_FALSE(cap.codeId.isEmpty());
|
||||
ASSERT_FALSE(cap.code.isEmpty());
|
||||
// 后端已把验证码从明文 code 改为图片 image(实测):自动化无法识别图内字符 → 跳过 live 登录断言。
|
||||
if (cap.code.isEmpty()) {
|
||||
ASSERT_FALSE(cap.image.isEmpty()) << "既无明文 code 也无图片 image,验证码接口异常";
|
||||
GTEST_SKIP() << "后端验证码改为图片(data.image),无明文 code,无法自动登录验证";
|
||||
}
|
||||
|
||||
auto* ll = auth.loginAsync("sydk", "123456", cap.code, cap.codeId);
|
||||
QSignalSpy loginDone(ll, &geopro::net::LoginLoad::done);
|
||||
|
|
|
|||
Loading…
Reference in New Issue