Swift 是不是;“错误”;要发出不带';不要调用sqlite3\u绑定?
我正在为MacOS游戏编写一个定制的SQLite包装器,这只是为了好玩。我已经学习了一个非常好的教程,它概述了一种使用绑定调用构造INSERT语句的费力方法,如下所示:Swift 是不是;“错误”;要发出不带';不要调用sqlite3\u绑定?,swift,sqlite,Swift,Sqlite,我正在为MacOS游戏编写一个定制的SQLite包装器,这只是为了好玩。我已经学习了一个非常好的教程,它概述了一种使用绑定调用构造INSERT语句的费力方法,如下所示: let insertStatementString = "INSERT INTO Contact (Id, Name) VALUES (?, ?);" insert(id:4, name:"Chris") func insert(id: Int32, name: NSString) { var insertState
let insertStatementString = "INSERT INTO Contact (Id, Name) VALUES (?, ?);"
insert(id:4, name:"Chris")
func insert(id: Int32, name: NSString) {
var insertStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
sqlite3_bind_int(insertStatement, 1, id)
sqlite3_bind_text(insertStatement, 2, name.utf8String, -1, nil)
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
} else {
print("INSERT statement could not be prepared.")
}
sqlite3_finalize(insertStatement)
}
相反,我发现以下方法同样有效,不必将数据绑定到语句。这样写有风险吗?我意识到准备好的陈述更快/更有效,但我不需要速度来达到我的目的。我没有看到像下面这样的例子。谢谢你的建议——我刚刚开始学习Swift,并不断发现事情比我想象的要难一些
let insertItemSql : String = "INSERT INTO item (itemid, characterClass,
itemtype, itemtypeid, mincharges, maxcharges, name) VALUES (%d,%d,%d,%d,%d,%d,'%@');"
let sqlHelper = SQLHelper(databasePath: Globals.SharedInstance.databaseUrl)
let command = String(format: insertItemSql, item.id, 0, 0, 0, 0, 0, item.name)
let success = sqlHelper.nonQuery(sqlCommand: command)
func nonQuery(sqlCommand cmd: String) -> Bool {
var success : Bool = false
if let db = openDatabase() {
var nonQueryStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, cmd, -1, &nonQueryStatement, nil) == SQLITE_OK {
if sqlite3_step(nonQueryStatement) == SQLITE_DONE {
success = true
} else {
print("Could not execute nonQuery statement.")
if let errorPointer = sqlite3_errmsg(db) {
let message = String.init(cString: errorPointer)
print("Error message was " + message)
}
}
} else {
print("nonQuery statement could not be prepared")
if let errorPointer = sqlite3_errmsg(db) {
let message = String.init(cString: errorPointer)
print("Error message was " + message)
}
}
sqlite3_finalize(nonQueryStatement)
}
return success
}
说它是“错误的”未免言过其实,但它可能是脆弱的,通常不被认为是最佳实践。那个教程的建议是一个很好的技巧 例如,如果与
name
列关联的值中有一个”
,该怎么办?例如“奥康纳”。此字符串中的单引号将提前终止SQL字符串,例如
INSERT INTO item (itemid, characterClass, itemtype, itemtypeid, mincharges, maxcharges, name)
VALUES (1,2,3,4,5,6,'O'Connor');
在这种情况下(除其他外),手动构造的SQL语句的准备可能会失败。sqlite3\u bind\u text
消除了此类问题,并且始终是安全的。正如上面所说:
然后使用函数将大字符串值绑定到SQL语句。使用绑定可以避免转义字符串中的引号字符,从而降低SQL注入攻击的风险。由于不需要对大字符串进行太多的解析或复制,因此它的运行速度也更快
当然,如果您知道您永远不会有任何有问题的输入(例如,您知道永远不会有任何这些有问题的值的只是数字或内部字符串值),那么您就不必使用sqlite3\u bind\u xxx
函数,但这种假设在以后会影响我们
一般来说,绑定值更安全。如果您担心sqlite3\u bind\u text
这类语法太麻烦,那么我可能会建议使用一个SQLite包装类为您进行绑定,但它会将您从这些细节中抽象出来
顺便说一句,绑定的另一个优点是用于
NULLABLE
列。如果只使用?
占位符,则可以为该列绑定NULL
或适当的值。如果您是手动构建SQL,正确处理可为null的
列只会稍微复杂一些。说它“错了”未免言过其实,但它可能很脆弱,通常不被视为最佳实践。那个教程的建议是一个很好的技巧
例如,如果与name
列关联的值中有一个”
,该怎么办?例如“奥康纳”。此字符串中的单引号将提前终止SQL字符串,例如
INSERT INTO item (itemid, characterClass, itemtype, itemtypeid, mincharges, maxcharges, name)
VALUES (1,2,3,4,5,6,'O'Connor');
在这种情况下(除其他外),手动构造的SQL语句的准备可能会失败。sqlite3\u bind\u text
消除了此类问题,并且始终是安全的。正如上面所说:
然后使用函数将大字符串值绑定到SQL语句。使用绑定可以避免转义字符串中的引号字符,从而降低SQL注入攻击的风险。由于不需要对大字符串进行太多的解析或复制,因此它的运行速度也更快
当然,如果您知道您永远不会有任何有问题的输入(例如,您知道永远不会有任何这些有问题的值的只是数字或内部字符串值),那么您就不必使用sqlite3\u bind\u xxx
函数,但这种假设在以后会影响我们
一般来说,绑定值更安全。如果您担心sqlite3\u bind\u text
这类语法太麻烦,那么我可能会建议使用一个SQLite包装类为您进行绑定,但它会将您从这些细节中抽象出来
顺便说一句,绑定的另一个优点是用于
NULLABLE
列。如果只使用?
占位符,则可以为该列绑定NULL
或适当的值。如果您是手动构建SQL,正确处理NULLABLE
列只会稍微复杂一些。我不同意。安全性很重要,但不是在涉及游戏的本地化环境中,也不是在应用程序域运行在一台机器上的情况下,我确实明确指出了这一点,希望防止像您这样的评论。感谢你阅读我的问题,但这不是我想要的。你没有抓住重点。问题不是SQL注入攻击,而是包含“
字符的用户输入将破坏代码。SQL注入是更广泛问题的恶意示例。但我会删除那个链接,因为你已经生气了。我不同意。安全性很重要,但不是在涉及游戏的本地化环境中,也不是在应用程序域运行在一台机器上的情况下,我确实明确指出了这一点,希望防止像您这样的评论。感谢你阅读我的问题,但这不是我想要的。你没有抓住重点。问题不是SQL注入攻击,而是包含“
字符的用户输入将破坏代码。SQL注入是更广泛问题的恶意示例。但我会删除那个链接,因为你已经生气了。没有一个是有意的。很容易对输入进行消毒。令我惊讶的是,我在SQLite文献中没有看到关于执行SAN绑定的可能性的示例。如果我在真实场景中使用SQL引擎,我会使用一个支持存储过程的引擎,该引擎的接口比这个低级C风格的API更健壮。关于可空性的观点很好。我没有考虑过这一点。哦,我不愿意