Ios 如何在sqlite查询中从NSString中删除
试图从这句话中删除“嘿,我明天来”。通过重复替换字符串也尝试了字符串,但它不起作用。请帮我找到解决办法,因为我已经在这上面浪费了半天多的时间了。下面是我尝试的查询和输出,请检查Ios 如何在sqlite查询中从NSString中删除,ios,objective-c,xcode,sqlite,Ios,Objective C,Xcode,Sqlite,试图从这句话中删除“嘿,我明天来”。通过重复替换字符串也尝试了字符串,但它不起作用。请帮我找到解决办法,因为我已经在这上面浪费了半天多的时间了。下面是我尝试的查询和输出,请检查 NSMutableString *msql = [[NSMutableString alloc] initWithFormat:@"insert into %@ ", tableName]; for (int i=0; i<[arrArguments count]; i++){
NSMutableString *msql = [[NSMutableString alloc] initWithFormat:@"insert into %@ ", tableName];
for (int i=0; i<[arrArguments count]; i++){
NSMutableArray *marrArgum = [arrArguments objectAtIndex:i];
if (i==0){
[msql appendFormat:@"SELECT '%@' AS 'id', '%@' AS 'UserID', '%@' AS 'MessageID', '%@' AS 'ActualMessage', '\%@\' AS 'MessageType', '%@' AS 'MessageIsOld', '%@' AS 'MessageSentBySelf', '%@' AS 'Timestamp', '%@' AS 'MessageRead', '%@' AS 'MessageToUser' ", [marrArgum objectAtIndex:0], [marrArgum objectAtIndex:1], [marrArgum objectAtIndex:2], [marrArgum objectAtIndex:3], [marrArgum objectAtIndex:4], [marrArgum objectAtIndex:5], [marrArgum objectAtIndex:6], [marrArgum objectAtIndex:7], [marrArgum objectAtIndex:8], [marrArgum objectAtIndex:9]];
}
else{
[msql appendFormat:@"UNION ALL SELECT '%@', '%@', '%@', '\%@\', '%@', '%@', '%@', '%@', '%@', '%@' ", [marrArgum objectAtIndex:0], [marrArgum objectAtIndex:1], [marrArgum objectAtIndex:2], [marrArgum objectAtIndex:3], [marrArgum objectAtIndex:4], [marrArgum objectAtIndex:5], [marrArgum objectAtIndex:6], [marrArgum objectAtIndex:7], [marrArgum objectAtIndex:8], [marrArgum objectAtIndex:9]];
}
NSString *sql = [NSString stringWithFormat: @"%@", msql];
DBLog(@"INSERT SQL QUERY: %@", sql);
METHOD_CALLER;
int intQcheck = sqlite3_exec(sqliteDB, [sql UTF8String], NULL, NULL, &err);
DBLog(@"intQcheck = %d", intQcheck);
if (intQcheck!= SQLITE_OK) {
if ([self targetAppIsUsingDevProfile])
NSAssert(0, @"Error in Insertion Query(intQcheck=%d): %@", intQcheck, strMsql);
success = NO;
}
但它不起作用。输出仍与之前相同,即:
i’ll see u you
请导游。谢谢。为什么准备好的声明会受到青睐
当您自己将SQL查询创建为字符串时,它们几乎总是包含用户输入的一部分。攻击者可以利用这一点,例如,使用“”巧妙地更改查询的语义,从而获得对数据的未经授权访问或销毁数据
这称为SQL注入,是最严重的安全风险之一,请参见此处:
防卫
将准备好的语句与变量绑定(又称参数化查询)结合使用是所有开发人员首先应该学习如何编写数据库查询的方式
如何在SQLite和iOS中使用准备好的语句
有关准备好的声明,请参见
基本步骤是:
创建准备好的语句
将值绑定到参数
运行SQL
销毁对象以避免资源泄漏
下面是一个简单的例子:
-(BOOL)insertValue:(NSString *)value intoDB:(sqlite3 *)db {
sqlite3_stmt *stmt = NULL;
NSString *insertStmt = @"insert into SomeTable (sometext) values (?)";
//create the prepared statement
if(SQLITE_OK == sqlite3_prepare_v2(db, insertStmt.UTF8String, -1, &stmt, NULL)) {
//bind values to parameters
if(SQLITE_OK == sqlite3_bind_text(stmt, 1, value.UTF8String, -1, SQLITE_STATIC)) {
//run the SQL
if(SQLITE_DONE != sqlite3_step(stmt)) {
return NO;
}
}
else {
return NO;
}
//destroy the object to avoid resource leaks
sqlite3_finalize(stmt);
}
else {
return NO;
}
return YES;
}
它将被称为您的示例字符串我将看到您这样:
sqlite3 *db;
if(SQLITE_OK == sqlite3_open(dbURL.absoluteString.UTF8String, &db)) {
NSString *someValue = @"i'll see u you";
if (![self insertValue:someValue intoDB:db]) {
NSLog(@"insert failed: '%s'", sqlite3_errmsg(db));
}
sqlite3_close(db);
}
else {
NSLog(@"open db failed: '%s'", sqlite3_errmsg(db));
}
因此,在这里使用“例如,来自用户输入的”不会造成任何伤害,因为我们使用的是预先准备好的语句
演示
如果查看数据库实用程序中的数据,则在insert语句之后如下所示:
替换为空字符串而不是\'?相同的输出没有变化'!='怎么样。一个是直的,另一个是弯的。这不是同一个字符。如果这样做,在替换时也复制相同的字符并粘贴到代码中,但不起作用。SQL语句与字符替换有什么关系?这两件事似乎与我完全无关。顺便说一句,答案末尾的你应该是实际答案。任何人都不应该使用字符串格式构建SQL查询。只使用准备好的语句。让底层SQLite API根据需要进行适当的引用和转义。这是SQL注入攻击的主要原因。@rmaddy您是对的,我不仅应该在回答的最后用一句话简单地提到这一点,而且明确指出这一点非常重要。我已经创建了一个小示例,并相应地重写了我的答案。@StephanSchlecht我的要求有点不同,所以我想我需要粘贴更多有问题的代码,以便清楚地理解。请再次检查我的问题,因为有几位评论员提到过,出于安全原因,不建议将SQL组装为字符串。再看一看我的例子,阅读参考文本。这需要适当的引用和转义。也就是说,如果要转义“以便在输出中显示为\”,则必须在替换中使用\',因此需要使用stringByReplacingOccurrencesOfString:@'with string:\\\']
sqlite3 *db;
if(SQLITE_OK == sqlite3_open(dbURL.absoluteString.UTF8String, &db)) {
NSString *someValue = @"i'll see u you";
if (![self insertValue:someValue intoDB:db]) {
NSLog(@"insert failed: '%s'", sqlite3_errmsg(db));
}
sqlite3_close(db);
}
else {
NSLog(@"open db failed: '%s'", sqlite3_errmsg(db));
}