Rails, how to sanitize SQL in find_by_sql

后端 未结 6 1268
孤城傲影
孤城傲影 2020-12-06 00:55

Is there a way to sanitize sql in rails method find_by_sql?

I\'ve tried this solution: Ruby on Rails: How to sanitize a string for SQL when not using fi

相关标签:
6条回答
  • 2020-12-06 01:20

    Though this example is for INSERT query, one can use similar approach for UPDATE queries. Raw SQL bulk insert:

    users_places = []
    users_values = []
    timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
    params[:users].each do |user|
        users_places << "(?,?,?,?)" # Append to array
        users_values << user[:name] << user[:punch_line] << timestamp << timestamp
    end
    
    bulk_insert_users_sql_arr = ["INSERT INTO users (name, punch_line, created_at, updated_at) VALUES #{users_places.join(", ")}"] + users_values
    begin
        sql = ActiveRecord::Base.send(:sanitize_sql_array, bulk_insert_users_sql_arr)
        ActiveRecord::Base.connection.execute(sql)
    rescue
        "something went wrong with the bulk insert sql query"
    end
    

    Here is the reference to sanitize_sql_array method in ActiveRecord::Base, it generates the proper query string by escaping the single quotes in the strings. For example the punch_line "Don't let them get you down" will become "Don\'t let them get you down".

    0 讨论(0)
  • Slightly more general-purpose:

    class ActiveRecord::Base  
      def self.escape_sql(clause, *rest)
        self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest))
      end
    end
    

    This one lets you call it just like you'd type in a where clause, without extra brackets, and using either array-style ? or hash-style interpolations.

    0 讨论(0)
  • 2020-12-06 01:30

    Try this:

    connect = ActiveRecord::Base.connection();
    connect.execute(ActiveRecord::Base.send(:sanitize_sql_array, "your string"))
    

    You can save it in variable and use for your purposes.

    0 讨论(0)
  • 2020-12-06 01:30
    User.find_by_sql(["SELECT * FROM users WHERE (name = ?)", params])
    

    Source: http://blog.endpoint.com/2012/10/dont-sleep-on-rails-3-sql-injection.html

    0 讨论(0)
  • 2020-12-06 01:39

    I prefer to do it with key parameters. In your case it may looks like this:

      Model.find_by_sql(["UPDATE user set active = :active where id = :id", active: 0, id: 1])
    

    Pay attention, that you pass ONLY ONE parameter to :find_by_sql method - its an array, which contains two elements: string query and hash with params (since its our favourite Ruby, you can omit the curly brackets).

    0 讨论(0)
  • 2020-12-06 01:42

    I made a little snippet for this that you can put in initializers.

    class ActiveRecord::Base  
      def self.escape_sql(array)
        self.send(:sanitize_sql_array, array)
      end
    end
    

    Right now you can escape your query with this:

    query = User.escape_sql(["Update users set active = ? where id = ?", true, params[:id]])
    

    And you can call the query any way you like:

    users = User.find_by_sql(query)
    
    0 讨论(0)
提交回复
热议问题