Objective c fmdb-使用like选择查询以避免sql注入

Objective c fmdb-使用like选择查询以避免sql注入,objective-c,ios,sqlite,fmdb,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]

大家好,祝大家圣诞快乐

我正在使用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]];
或者类似于:

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子句(“%%?%%”)周围的单引号或单引号而不是双引号,也会发生同样的情况

你能告诉我这个问题吗? 任何帮助都将不胜感激

新年快乐

您上次的尝试(没有任何引号)是正确的语法。您是否正在检查
结果
是否为非
?如果
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];

顺便说一句,如果您很挑剔,并且不希望最终用户操纵参数或得到不直观的响应(并且不希望最终用户应用自己的通配符),您可能希望避免出现通配符,例如
%
,使用
ESCAPE
SQL语法。因此,您可能希望为转义字符定义一个常量:

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
转义
%
\uuu
,以及通配符本身。因此:

- (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]];
}
通过这种方式,您可以搜索任何字符串,包括带有多字符通配符的字符串,
/
,或带有单字符通配符的字符串,
\u

您上次尝试(没有任何引号)的语法是正确的。您是否正在检查
结果
是否为非
?如果
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];

顺便说一句,如果您很挑剔,并且不希望最终用户操纵参数或得到不直观的响应(并且不希望最终用户应用自己的通配符),您可能希望避免出现通配符,例如
%
,使用
ESCAPE
SQL语法。因此,您可能希望为转义字符定义一个常量:

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
转义
%
\uuu
,以及通配符本身。因此:

- (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]];
}

通过这种方式,您可以搜索任何字符串,包括带有多字符通配符的字符串,
/
,或带有单字符通配符的字符串,
\uu

+1我很高兴您能正确处理这一事实。太多人使用用户提供的字段轻松地使用
stringWithFormat
构建SQL,而不考虑在用户字段中意外或故意使用引号字符。无论何时使用用户提供的数据,都应使用
占位符。在太多的应用程序中,搜索乔的“鱼屋”是有问题的。+1我喜欢你能正确处理这个事实。太多人使用用户提供的字段轻松地使用
stringWithFormat
构建SQL,而不考虑在用户字段中意外或故意使用引号字符。无论何时使用用户提供的数据,都应使用
占位符。在太多的应用程序中,搜索Joe的“鱼屋”是有问题的。非常感谢Rob!这两个建议(逃脱或不逃脱)对我都有好处!谢谢你的彻底回答,罗布!这两个建议(逃脱或不逃脱)对我都有好处!Thanx也提供了完整的答案