You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Drogon简易认证机制中execSqlAsync函数模板错误求助

问题

基于Drogon框架实现简易认证机制,采用凯撒密码加密,但所有execSqlAsync调用都出现模板错误,错误信息如下:

In template: invalid operands to binary expression ('std::stringstream' (aka 'basic_stringstream<char>') and 'std::exception') error occurred here in instantiation of function template specialization 'drogon::orm::Field::as<std::exception>' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at /Users/<br>
41:13)>::makeValue<std::exception>' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at /Users/<br>
41:13)>::run<1UL>' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at <br>
41:13)>::run<true>' requested here in instantiation of member function 'drogon::orm::internal::CallbackHolder<(lambda at /Users/<br>
41:13)>::execCallback' requested here in instantiation of function template specialization 'drogon::orm::internal::CallbackHolder<(lambda at /Users/<br>
41:13)>::CallbackHolder<(lambda at patr... in instantiation of function template specialization 'drogon::orm::internal::SqlBinder::operator>> <(lambda at <br>
server/AuthController.cpp:41:13), drogon::orm::internal::FunctionTraits<(lambda at /U... in instantiation of function template specialization 'drogon::orm::DbClient::execSqlAsync<(lambda at <br> server/AuthController.cpp:35:13), (lambda at /<br> server/A... candidate template ignored: deduced conflicting types for parameter '_CharT' ('char' vs. 'std::exception') candidate template ignored: could not match 'uniform_int_distribution<_IT>' against 'std::exception' candidate template ignored: could not match '_CharT[_Np]' against 'std::exception' candidate template ignored: could not match 'unsigned char[_Np]' against 'std::exception' candidate template ignored: could not match 'signed char[_Np]' against 'std::exception' candidate template ignored: could not match 'basic_string<_CharT, _Traits, _Allocator>' against 'std::exception' candidate template ignored: could not match 'bitset<_Size>' against 'std::exception' candidate template ignored: requirement 'integral_constant<bool, false>::value' was not satisfied [with _Stream = std::stringstream &, _Tp = std::exception &] candidate template ignored: could not match '__iom_t7<_MoneyT>' against 'std::exception' candidate template ignored: could not match '__iom_t9<_CharT>' against 'std::exception'

对应的实现代码:

#include "AuthController.h"
#include <drogon/drogon.h>
#include <drogon/orm/DbClient.h>
#include <algorithm>

using namespace drogon;
using namespace drogon::orm;

// Simple Caesar Cipher function
std::string caesarCipher(const std::string& text, int shift) {
    std::string result = text;
    std::transform(result.begin(), result.end(), result.begin(),
                   [shift](char c) -> char {
                       if (c >= 'a' && c <= 'z')
                           return 'a' + (c - 'a' + shift) % 26;
                       else if (c >= 'A' && c <= 'Z')
                           return 'A' + (c - 'A' + shift) % 26;
                       else
                           return c;
                   });
    return result;
}

void AuthController::signup(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
    auto json = req->getJsonObject();
    std::string username = json->get("username", "").asString();
    std::string password = json->get("password", "").asString();

    // Encrypt the password using Caesar cipher
    std::string encryptedPassword = caesarCipher(password, 3);

    auto client = drogon::app().getDbClient().get();
    client->execSqlAsync(
            "INSERT INTO users (username, password_hash) VALUES ($1, $2)",
            [callback](const Result &result) {
                auto response = HttpResponse::newHttpResponse();
                response->setStatusCode(HttpStatusCode::k200OK);
                response->setBody("Signup successful");
                callback(response);
            },
            [callback](const std::exception &e) {  // Correct exception handling
                auto response = HttpResponse::newHttpResponse();
                response->setStatusCode(HttpStatusCode::k500InternalServerError);
                response->setBody(e.what());
                callback(response);
            },
            username, encryptedPassword);
}

void AuthController::login(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
    auto json = req->getJsonObject();
    std::string username = json->get("username", "").asString();
    std::string password = json->get("password", "").asString();

    auto client = drogon::app().getDbClient();
    client.get()->execSqlAsync(
            "SELECT password_hash FROM users WHERE username = $1",
            [password, callback](const Result &result) {
                std::shared_ptr<HttpResponse> response;
                if (!result.empty()) {
                    std::string storedHash = result[0]["password_hash"].as<std::string>();
                    std::string decryptedPassword = caesarCipher(storedHash, -3);
                    if (decryptedPassword == password) {
                        response = HttpResponse::newHttpResponse();
                        response->setStatusCode(k200OK);
                        response->setBody("Login successful");
                    } else {
                        response = HttpResponse::newHttpResponse();
                        response->setStatusCode(k401Unauthorized);
                        response->setBody("Login failed");
                    }
                } else {
                    response = HttpResponse::newHttpResponse();
                    response->setStatusCode(k401Unauthorized);
                    response->setBody("User not found");
                }
                callback(response);
            },
            [callback](const std::exception &e) {
                auto resp = HttpResponse::newHttpResponse();
                resp->setStatusCode(k500InternalServerError);
                resp->setBody(e.what());
                callback(resp);
            },
            username);
}
分析与解决

问题原因

Drogon的execSqlAsync函数对错误回调的参数类型有严格要求:它需要接收const DrogonDbException&而非const std::exception&。代码中错误地使用了std::exception,导致模板推导时把它当成了要从数据库字段解析的类型,进而尝试用std::stringstream转换std::exception,触发类型不匹配的错误。

修复步骤

  1. 将两个execSqlAsync调用中的错误回调参数类型从const std::exception &e改为const DrogonDbException &e。
  2. 添加DrogonDbException对应的头文件:#include <drogon/orm/DrogonDbException.h>。

修复后的代码

#include "AuthController.h"
#include <drogon/drogon.h>
#include <drogon/orm/DbClient.h>
#include <drogon/orm/DrogonDbException.h> // 添加该头文件
#include <algorithm>

using namespace drogon;
using namespace drogon::orm;

// Simple Caesar Cipher function
std::string caesarCipher(const std::string& text, int shift) {
    std::string result = text;
    std::transform(result.begin(), result.end(), result.begin(),
                   [shift](char c) -> char {
                       if (c >= 'a' && c <= 'z')
                           return 'a' + (c - 'a' + shift) % 26;
                       else if (c >= 'A' && c <= 'Z')
                           return 'A' + (c - 'A' + shift) % 26;
                       else
                           return c;
                   });
    return result;
}

void AuthController::signup(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
    auto json = req->getJsonObject();
    std::string username = json->get("username", "").asString();
    std::string password = json->get("password", "").asString();

    // Encrypt the password using Caesar cipher
    std::string encryptedPassword = caesarCipher(password, 3);

    auto client = drogon::app().getDbClient().get();
    client->execSqlAsync(
            "INSERT INTO users (username, password_hash) VALUES ($1, $2)",
            [callback](const Result &result) {
                auto response = HttpResponse::newHttpResponse();
                response->setStatusCode(HttpStatusCode::k200OK);
                response->setBody("Signup successful");
                callback(response);
            },
            // 修改错误回调参数类型
            [callback](const DrogonDbException &e) {
                auto response = HttpResponse::newHttpResponse();
                response->setStatusCode(HttpStatusCode::k500InternalServerError);
                response->setBody(e.what());
                callback(response);
            },
            username, encryptedPassword);
}

void AuthController::login(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
    auto json = req->getJsonObject();
    std::string username = json->get("username", "").asString();
    std::string password = json->get("password", "").asString();

    auto client = drogon::app().getDbClient();
    client.get()->execSqlAsync(
            "SELECT password_hash FROM users WHERE username = $1",
            [password, callback](const Result &result) {
                std::shared_ptr<HttpResponse> response;
                if (!result.empty()) {
                    std::string storedHash = result[0]["password_hash"].as<std::string>();
                    std::string decryptedPassword = caesarCipher(storedHash, -3);
                    if (decryptedPassword == password) {
                        response = HttpResponse::newHttpResponse();
                        response->setStatusCode(k200OK);
                        response->setBody("Login successful");
                    } else {
                        response = HttpResponse::newHttpResponse();
                        response->setStatusCode(k401Unauthorized);
                        response->setBody("Login failed");
                    }
                } else {
                    response = HttpResponse::newHttpResponse();
                    response->setStatusCode(k401Unauthorized);
                    response->setBody("User not found");
                }
                callback(response);
            },
            // 修改错误回调参数类型
            [callback](const DrogonDbException &e) {
                auto resp = HttpResponse::newHttpResponse();
                resp->setStatusCode(k500InternalServerError);
                resp->setBody(e.what());
                callback(resp);
            },
            username);
}

内容的提问来源于stack exchange,提问作者yagil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 21:25:53