一般情況下,你不應該使用字符串插值來建立SQL查詢。這樣做會使您打開SQL injection攻擊,其中有人提供具有結束引號字符的輸入,然後是另一個查詢。舉例來說,使用例如:
>> val = '7; DROP TABLE users;'
=> "7; DROP TABLE users;"
>> myQuery = "select * from t where t.val = \#{val}"
=> "select * from t where t.val = \#{val}"
>> eval "\"#{myQuery}\""
=> "select * from t where t.val = 7; DROP TABLE users;"
即使沒有惡意輸入,你可以簡單地執行意外,你是不打算代碼,舉例來說如果有人列入其輸入引號。
除非絕對必要,避免使用eval
也是一個好主意;它使得如果你的程序中有一個bug,有人可以通過將它傳遞給eval
來執行任意代碼,並且由於你的一些源代碼將從常規源代碼樹以外的地方加載,所以它使得代碼不易維護。
那麼,你是如何做到這一點呢?數據庫API通常包括一個prepare
命令,該命令可以準備執行一條SQL語句。在該語句中,您可以包含?
字符,它們表示可以在該語句中替換的參數。然後,您可以在語句上調用execute
,爲這些參數傳入值,並且它們將被安全地執行,無法讓某人執行任意一段SQL。
下面是它在你的例子中的工作原理。這假設你正在使用this MySQL/Ruby module;如果您使用的是不同的界面,它可能會有類似的界面,儘管它可能不完全相同。
>> val = 7
>> db = Mysql.new(hostname, username, password, databasename)
>> query = db.prepare("select * from t where t.val = ?")
>> query.execute(val)