LibCurl 和 Sql 命令
LibCurl & Sql Commands
我是c++的初学者,有两个小问题。
1 - 我想获取用户的 public ip 地址。为此,我像这样使用 curl :
CURL* curl;
CURLcode verif;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "https://ifconfig.me/?action=render");
verif = curl_easy_perform(curl);
curl_easy_cleanup(curl);
但是当我 运行 程序写入 IP 但我不确定如何将其存储到变量中。我应该怎么做才能实现这一目标?
2 - 我想向数据库发送请求,但我的语法有一些问题。
我的代码:
int query_state = mysql_query(db, "INSERT INTO `account` (`id`, `id_user`, `ip`, `last_join`) VALUES (NULL, '" << id << "', '" << ip_user << "', '" << date << "')");
但是我对“<<”有错误。错误在请求中:(NULL, ' " << id
在此先感谢您的帮助。
如果您只对 IP 地址感兴趣,没有其他兴趣,请查询 https://ifconfig.me/ip instead of https://ifconfig.me/?action=render. And then use a CURLOPT_WRITEFUNCTION
回调以将该输出保存到变量,例如 std::string
,例如:
size_t write_str(char *ptr, size_t size, size_t nmemb, void *userdata);
{
size_t numBytes = size * nmemb;
static_cast<std::string*>(userdata)->append(ptr, numBytes);
return numBytes;
}
...
std::string ip_user;
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "https://ifconfig.me/ip");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_str);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ip_user);
CURLcode verif = curl_easy_perform(curl);
curl_easy_cleanup(curl);
至于数据库,您不能使用 <<
以您尝试的方式连接字符串。这就是您从编译器中收到错误的原因。
如果你真的想用<<
拼接那么你需要用一个std::ostringstream
来收集子串,然后你可以调用它的str()
方法来提取已完成 std::string
,例如:
#include <sstream>
std::ostringstream oss;
oss << "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, '" << id << "', '" << ip_user << "', '" << date << "')";
std::string sql = oss.str();
int query_state = mysql_query(db, sql.c_str());
否则,只需使用普通字符串 +
连接即可:
std::string sql = "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, '" + id + "', '" + ip_user + "', '" + date + "')";
int query_state = mysql_query(db, sql.c_str());
话虽如此,请注意 SQL 语句的这种手动构建容易受到 SQL 注入攻击。为了避免此类攻击,您必须转义您的输入字符串,例如使用 mysql_real_escape_string_quote()
,这样攻击者就无法为您提供格式错误的输入,从而破坏您的 SQL 语句以执行恶意操作,例如:
std::string sql_escape(MYSQL *db, const std::string &s char quote = '\'')
{
std::string escaped;
escaped.resize((s.length() * 2) + 1);
escaped.resize(mysql_real_escape_string_quote(db, &escaped[0], s.c_str(), s.length(), quote));
return escaped;
}
std::ostringstream oss;
oss << "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, " << sql_escape(db, id) << ", " << sql_escape(db, ip_user) << ", " << sql_escape(db, date) << ")";
std::string sql = oss.str();
...
std::string sql = "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, " + sql_escape(db, id) + ", " + sql_escape(db, ip_user) + ", " + sql_escape(db, date) + ")";
...
更好的选择是使用参数化查询。这不仅会堵塞此类攻击的漏洞,而且还会让数据库为您处理任何必要的输入字符串转义,例如:
std::string sql = "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, ?, ?, ?)";
MYSQL_BIND params[3] = {};
params[0].buffer_type = MYSQL_TYPE_STRING;
params[0].buffer = &id[0]; // or id.data() in C++17
params[0].buffer_length = params[0].length = id.length();
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = &ip_user[0]; // or ip_user.data() in C++17
params[1].buffer_length = params[1].length = ip_user.length();
params[2].buffer_type = MYSQL_TYPE_STRING;
params[2].buffer = &date[0]; // or date.data() in C++17
params[2].buffer_length = params[2].length = date.length();
MYSQL_STMT *stmt = mysql_stmt_init(db);
mysql_stmt_prepare(stmt, sql.c_str(), sql.length());
mysql_stmt_bind_param(stmt, params);
mysql_stmt_execute(stmt);
mysql_stmt_close(stmt);
我是c++的初学者,有两个小问题。
1 - 我想获取用户的 public ip 地址。为此,我像这样使用 curl :
CURL* curl;
CURLcode verif;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "https://ifconfig.me/?action=render");
verif = curl_easy_perform(curl);
curl_easy_cleanup(curl);
但是当我 运行 程序写入 IP 但我不确定如何将其存储到变量中。我应该怎么做才能实现这一目标?
2 - 我想向数据库发送请求,但我的语法有一些问题。 我的代码:
int query_state = mysql_query(db, "INSERT INTO `account` (`id`, `id_user`, `ip`, `last_join`) VALUES (NULL, '" << id << "', '" << ip_user << "', '" << date << "')");
但是我对“<<”有错误。错误在请求中:(NULL, ' " << id
在此先感谢您的帮助。
如果您只对 IP 地址感兴趣,没有其他兴趣,请查询 https://ifconfig.me/ip instead of https://ifconfig.me/?action=render. And then use a CURLOPT_WRITEFUNCTION
回调以将该输出保存到变量,例如 std::string
,例如:
size_t write_str(char *ptr, size_t size, size_t nmemb, void *userdata);
{
size_t numBytes = size * nmemb;
static_cast<std::string*>(userdata)->append(ptr, numBytes);
return numBytes;
}
...
std::string ip_user;
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "https://ifconfig.me/ip");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_str);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ip_user);
CURLcode verif = curl_easy_perform(curl);
curl_easy_cleanup(curl);
至于数据库,您不能使用 <<
以您尝试的方式连接字符串。这就是您从编译器中收到错误的原因。
如果你真的想用<<
拼接那么你需要用一个std::ostringstream
来收集子串,然后你可以调用它的str()
方法来提取已完成 std::string
,例如:
#include <sstream>
std::ostringstream oss;
oss << "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, '" << id << "', '" << ip_user << "', '" << date << "')";
std::string sql = oss.str();
int query_state = mysql_query(db, sql.c_str());
否则,只需使用普通字符串 +
连接即可:
std::string sql = "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, '" + id + "', '" + ip_user + "', '" + date + "')";
int query_state = mysql_query(db, sql.c_str());
话虽如此,请注意 SQL 语句的这种手动构建容易受到 SQL 注入攻击。为了避免此类攻击,您必须转义您的输入字符串,例如使用 mysql_real_escape_string_quote()
,这样攻击者就无法为您提供格式错误的输入,从而破坏您的 SQL 语句以执行恶意操作,例如:
std::string sql_escape(MYSQL *db, const std::string &s char quote = '\'')
{
std::string escaped;
escaped.resize((s.length() * 2) + 1);
escaped.resize(mysql_real_escape_string_quote(db, &escaped[0], s.c_str(), s.length(), quote));
return escaped;
}
std::ostringstream oss;
oss << "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, " << sql_escape(db, id) << ", " << sql_escape(db, ip_user) << ", " << sql_escape(db, date) << ")";
std::string sql = oss.str();
...
std::string sql = "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, " + sql_escape(db, id) + ", " + sql_escape(db, ip_user) + ", " + sql_escape(db, date) + ")";
...
更好的选择是使用参数化查询。这不仅会堵塞此类攻击的漏洞,而且还会让数据库为您处理任何必要的输入字符串转义,例如:
std::string sql = "INSERT INTO account (id, id_user, ip, last_join) VALUES (NULL, ?, ?, ?)";
MYSQL_BIND params[3] = {};
params[0].buffer_type = MYSQL_TYPE_STRING;
params[0].buffer = &id[0]; // or id.data() in C++17
params[0].buffer_length = params[0].length = id.length();
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = &ip_user[0]; // or ip_user.data() in C++17
params[1].buffer_length = params[1].length = ip_user.length();
params[2].buffer_type = MYSQL_TYPE_STRING;
params[2].buffer = &date[0]; // or date.data() in C++17
params[2].buffer_length = params[2].length = date.length();
MYSQL_STMT *stmt = mysql_stmt_init(db);
mysql_stmt_prepare(stmt, sql.c_str(), sql.length());
mysql_stmt_bind_param(stmt, params);
mysql_stmt_execute(stmt);
mysql_stmt_close(stmt);