#include "AuthService.hpp" #include #include #include #include "ApiChain.hpp" #include "ApiClient.hpp" #include "AuthLoads.hpp" #include "crypto/RsaEncryptor.hpp" namespace geopro::net { namespace { constexpr int kCodeSuccess = 200; const char* const kPathImageCode = "/business/system/personalUser/getImageCode"; const char* const kPathVerifyCode = "/business/system/personalUser/verifyCodeCheck"; const char* const kPathLogin = "/admin/tenant/auth/login2"; } // namespace AuthService::AuthService(ApiClient& api, std::string rsaPublicKeyPem) : api_(api), rsaPublicKeyPem_(std::move(rsaPublicKeyPem)) {} CaptchaLoad* AuthService::fetchCaptchaAsync() { IApiCall* call = api_.getAsync(QString::fromLatin1(kPathImageCode)); return new CaptchaLoad(call); } LoginLoad* AuthService::loginAsync(const QString& username, const QString& password, const QString& code, const QString& codeId) { // 失败判定与同步版一致:服务端 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&) -> 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&) -> 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("codeId"), codeId}}; return api_.postJsonAsync(QString::fromLatin1(kPathLogin), body); }; auto* chain = new ApiChain({step1, step2}, isFailure); return new LoginLoad(chain); } } // namespace geopro::net