2012-03-19 92 views
0

我創建了以下ruby腳本,它可以登錄到mysql數據庫並根據用戶輸入的用戶名和密碼返回訂單信息。我的問題是我將如何去防止sql注入?我知道現在寫的方式讓它可以廣泛應用於攻擊,但是我對ruby很陌生,我不知道如何去防止這種情況。通過ruby腳本防止SQL注入

#!/usr/bin/ruby 

#Import mysql module 
    require "mysql" 

    begin 

    #Establish connection to mysql database as the operator user. 
    connection = Mysql.real_connect("localhost", "operator", "", "rainforest") 
    #Allow Multi line statements 
    connection.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON) 

    #Prompt user for username 
    puts "Please Enter Your Customer Username:" 
    #Get username entered and store to variable 
    username = gets.chomp 

    #Prompt user for password 
    puts "Please Enter Your Customer Password" 
    #Get password entered and store to variable 
    password = gets.chomp 

    #Specify SQL query that returns order if user entered data matches data held in customer table 
    customerQuery = connection.query("SELECT O.order_ID, O.date_ordered, C.customer_name, P.product_name 
    FROM orders As O 
    INNER JOIN customer As C ON O.customer_ID=C.customer_ID 
    INNER JOIN product As P ON O.product_ID=P.product_ID 
    WHERE C.customer_name = '" + name + "' AND C.customer_password = '" + password + "'") 

    #If query returns a row then user has entered correct login details 
    if customerQuery.num_rows > 0 then 

    #tell user they have successfully logged in 
    puts "User Successfully Authenticated: Hello " + username + ". Here are your orders:  \n**********" 

    #Print all row data containing users order details to screen 
    while row = customerQuery.fetch_row do 

    puts row 
    puts "**********"  
    end 
    else 
    #if no rows return, user has entered incorrect details, inform them of this by printing to screen 
    puts "User Authentication Unsuccessful:Incorrect Username or Password, Please Try  Again" 
    end 
    #close connection to database 
    connection.close 
    end 

回答

2

使用事先準備好的聲明,而不是字符串連接/插值:

p = connection.prepare(%q{ 
    select o.order_id, o.date_ordered, c.customer_name, p.product_name 
    from orders as o 
    join customer as c on o.customer_id = c.customer_id 
    join product as p on o.product_id = p.product_id 
    where c.customer_name  = ? 
     and c.customer_password = ? 
}) 
customerQuery = p.execute(name, password) 
if customerQuery.num_rows > 0 
    customerQuery.each do |row| 
     #... 
    end 
else 
    #... 
end 

如果你絕對必須使用字符串插值理由很奇怪,然後使用connection.quote

customerQuery = connection.query(%Q{ 
    select o.order_id, o.date_ordered, c.customer_name, p.product_name 
    from orders as o 
    join customer as c on o.customer_id = c.customer_id 
    join product as p on o.product_id = p.product_id 
    where c.customer_name  = '#{connection.quote(name)}' 
     and c.customer_password = '#{connection.quote(password)}' 
}) 

不過說真的,除非你別無選擇,否則不要這樣做。在這種情況下,您不必爲此使用字符串操作。