fmdb - 选择查询,以避免sql注入

时间:2012-12-28 11:24:28

标签: objective-c ios sqlite fmdb

大家好,祝大家圣诞快乐!

我正在使用sqlite和fmdb构建一个iOS应用程序作为包装器。 我正在尝试执行以下sql语句:

SELECT * FROM TABLE WHERE FIELD LIKE '%text%'

文本来自UISearchBar。

到目前为止,我使用它的唯一方法是使用以下代码:

NSString *query = [NSString stringWithFormat:@"SELECT * FROM TABLE WHERE FIELD LIKE '%%%@%%'", text];
FMResultSet *results = [db executeQuery:query];

请注意我只发布查询代码。效果很好。

我想要的是避免sql注入,所以我尝试的是:

NSString *query = @"SELECT * FROM TABLE WHERE FIELD LIKE %%?%%";
FMResultSet *results = [db executeQuery:query, text];

或类似的东西:

NSString *query = @"SELECT * FROM TABLE WHERE FIELD LIKE ?";
FMResultSet *results = [db executeQuery:query, [NSString stringWithFormat:@"%%%@%%", text]];

不起作用。围绕like子句('%%?%%')或单个%而不是double的单引号也是如此。

你能指导我解决这个问题吗? 任何帮助将不胜感激!

新年快乐!

1 个答案:

答案 0 :(得分:3)

您上次尝试(没有任何引号)是正确的语法。您是否在查看results是否为非nil?如果是nil,则应检查错误字符串。例如,这有效:

NSString *searchString = @"larry";
NSString *likeParameter = [NSString stringWithFormat:@"%%%@%%", searchString];
NSString *sql = @"SELECT text_column FROM test WHERE text_column LIKE ?";

FMResultSet *results = [db executeQuery:sql, likeParameter];

if (!results)
{
    NSLog(@"error: %@", [db lastErrorMessage]);
    [db close];
    return;
}

while ([results next])
{
    NSLog(@"%s: %@", __FUNCTION__, results[0]);
}

[results close];
[db close];

顺便说一句,如果你是特殊的并且你不希望最终用户操纵参数或得到不直观的响应(并且你不希望最终用户使用他们自己的通配符),你可能想要使用% SQL语法转义通配符的出现,例如_ESCAPE。因此,您可能希望为转义字符定义常量:

NSString * const kEscapeCharacter = @"\\";

然后,构建您的SQL,如:

NSString *likeParameter = [NSString stringWithFormat:@"%%%@%%", [self escapedLikeParameter:searchString]];
NSString *sql = [NSString stringWithFormat:@"SELECT text_column FROM test WHERE text_column LIKE ? ESCAPE '%@'", kEscapeCharacter];

escapedLikeParameter转义%_和通配符本身。因此:

- (NSString *)escapedLikeParameter:(NSString *)string
{
    NSString *escapedString;
    escapedString = [string stringByReplacingOccurrencesOfString:kEscapeCharacter
                                                                withString:[NSString stringWithFormat:@"%@%@", kEscapeCharacter, kEscapeCharacter]];
    escapedString = [escapedString stringByReplacingOccurrencesOfString:@"_"
                                                             withString:[NSString stringWithFormat:@"%@_", kEscapeCharacter]];
    return [escapedString stringByReplacingOccurrencesOfString:@"%"
                                                    withString:[NSString stringWithFormat:@"%@%%", kEscapeCharacter]];
}

这样,您可以搜索任何字符串,包括具有多字符通配符/或单字符通配符_的字符串。