How to sanitize sql fragment in Rails

前端 未结 6 576
南方客
南方客 2021-02-01 13:28

I have to sanitize a part of sql query. I can do something like this:

class << ActiveRecord::Base
  public :sanitize_sql
end

str = ActiveRecord::Base.sani         


        
相关标签:
6条回答
  • 2021-02-01 14:08

    This question does not specify that the answer has to come from ActiveRecord nor does it specify for which version of Rails it should be. For that reason (and because it is one of the top and few) answers on how to sanitize parameters in Rails...


    Here a solution that works with Rails 4:

    In ActiveRecord::Sanitization::ClassMethods you have sanitize_sql_for_conditions and its two other aliases:  sanitize_conditions and sanitize_sql. The three do literally the exact same thing.

    sanitize_sql_for_conditions

    Accepts an array, hash, or string of SQL conditions and sanitizes them into a valid SQL fragment for a WHERE clause.

    Also in ActiveRecord you have

    sanitize_sql_for_assignment which

    Accepts an array, hash, or string of SQL conditions and sanitizes them into a valid SQL fragment for a SET clause.

    • The methods above are included in ActiveRecord::Base by default and therefore are included in any ActiveRecord model.

    See docs


    Also, however, in ActionController you have ActionController::Parameters which allows you to

    choose which attributes should be whitelisted for mass updating and thus prevent accidentally exposing that which shouldn't be exposed. Provides two methods for this purpose: require and permit.

       

    params = ActionController::Parameters.new(user: { name: 'Bryan', age: 21 })
    req  = params.require(:user) # will throw exception if user not present
    opt  = params.permit(:name)  # name parameter is optional, returns nil if not present
    user = params.require(:user).permit(:name, :age) # user hash is required while `name` and `age` keys are optional
    

    The "Parameters magic" is called Strong Parameters (docs here) and you can use that to sanitize parameters in a controller before sending it to a model.

    • The methods above are included by default in ActionController::Base and therefore are included in any Rails controller.

    I hope that helps anyone, if only to learn and demystify Rails! :)

    0 讨论(0)
  • 2021-02-01 14:13

    You can just use:

    ActiveRecord::Base::sanitize_sql(string)
    
    0 讨论(0)
  • 2021-02-01 14:17

    Note that when it comes to sanitizing SQL WHERE conditions, the best solution was sanitize_sql_hash_for_conditions, because it correctly handled NULL conditions (e.g. would generate IS NULL instead of = NULL if a nil attribute was passed).

    For some reason, it was deprecated in Rails 5. So I rolled a future-proofed version, see here: https://stackoverflow.com/a/53948665/165673

    0 讨论(0)
  • 2021-02-01 14:28

    You can bypass the protectedness of the method by invoking indirectly:

    str = ActiveRecord::Base.__send__(:sanitize_sql, ["AND column1 = ?", "two's"], '')
    

    ... which will at least spare you having to refashion that method as public.

    (I'm a bit suspicious that you actually need to do this, but the above will work.)

    0 讨论(0)
  • 2021-02-01 14:32

    ActiveRecord::Base.connection.quote does the trick in Rails 3.x

    0 讨论(0)
  • 2021-02-01 14:32

    As of rails 5 the recomended way is to use: ActiveRecord::Base.connection.quote(string)

    as stated here: https://github.com/rails/rails/issues/28947

    ActiveRecord::Base::sanitize(string) is deprecated

    0 讨论(0)
提交回复
热议问题