我有一个使用AES128加密的C ++ std::string
,并希望将其写入sqllite数据库。我已经知道,我必须使用'
和''
"
转义""
个字符,但似乎还有其他问题。
它说:
unrecognized token: "'""\235\211g\264\376\247\3348( ]tu\202\346\360\226h\205D\322-\373\347y"
我的查询如下:
UPDATE tablename
SET column='""\235\211g\264\376\247\3348( ]tu\202\346\360\226h\205D\322-\373\347y\315\|`\3206\245\220j6
\215&\301ww/\222R\352]\253,\362&\233ï\2530\322搜\377\321!\334t\224\271ќVu\214Z\\256""\242O\254\241\254\365\360<P\364\356\370\225jnۢ\231\335($\243\377fH\225\215\224\223\254\316'
WHERE index='1';
使用未加密字符串的相同查询有效。有什么想法吗?
答案 0 :(得分:4)
你做错了。
您不应该永远,在查询中完整地写出参数;但您应该使用绑定参数:Binding Values To Prepared Statements。
主要优势?绑定参数不必转义,这完全可以防止SQL注入的任何风险,并且还大大简化了您的生活!
此外,准备好的陈述可以重复使用以提高效率,所以让我举一个完整的例子。
//
// WARNING: for concision purposes there is no error handling
// and no attempt at making this code even remotely exception-safe.
//
// !!! DO NOT USE IN REAL LIFE !!!
//
void update(std::map<int, std::string> const& blobs) {
// 1. Prepare statement
sqlite3_stmt *stmt;
sqlite3_prepare(db,
"update tablename set column = ? where index = ?",
-1, // statement is a C-string
&stmt,
0 // Pointer to unused portion of stmt
);
// 2. Use statement as many times as necessary
for (auto const& pair: blobs) {
int const index = pair.first;
std::string const& blob = pair.second;
// 2.1 Bind 1st parameter
sqlite3_bind_text(stmt,
1, // 1-based index: 1st parameter
blob.data(),
blob.size(),
0 // no need for sqlite to free this argument
);
// 2.2 Bind 2nd parameter
sqlite3_bind_int(stmt,
2, // 1-based index: 2nd parameter
index
);
// 2.3 Execute statement
sqlite3_step(stmt);
// 2.4 Reset bindings
sqlite3_reset(stmt);
}
// 3. Free prepared query
sqlite3_finalize(stmt);
} // update
注意:您当然可以将准备好的陈述保持更长时间。