2012-12-28 115 views
2

大家好,祝大家聖誕快樂!fmdb - 選擇與喜歡的查詢,以避免sql注入

我正在構建一個使用sqlite和fmdb作爲包裝的iOS應用程序。 我試圖執行下面的SQL語句:從一個UISearchBar來的文本

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

截至目前唯一的辦法,我得到它的工作是用下面的代碼:

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

+1我喜歡你正確處理這個事實。太多的人在用戶提供的字段中使用'stringWithFormat'輕鬆地構建他們的SQL,而不考慮在用戶字段中意外或故意使用引號字符。每當使用用戶提供的數據時,都應該使用'?'佔位符。在太多的應用程序中,搜索「Joe's」Fish House「」是有問題的。 – Rob

回答

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

順便說一句,如果你是特別的,你不希望最終用戶操作的參數或得到直觀的反應(你不希望最終用戶應用自己的通配符),則可能需要使用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逃脫%_,和通配符本身。因此:

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

這樣的話,你可以搜索任何字符串,包括那些具有多字符通配符/,或單個字符通配符,_

+1

非常感謝Rob!這兩個建議(逃脫或不)爲我做的伎倆!感謝徹底的答覆 – ozzotto