我最近偶然发现了api的一部分,用户可以在其中查询特定字段:
api/models?only=id,name
它是这样实现的:
@model = Model.select params[:only]
对于这一行我有一种安静的不好的感觉,如果有可能将sql注入代码的这一部分......我就试过了......
经过一番思考后我们想出了这个
@model = Model.select params[:only].split(',').map(&:to_sym)
这实际上可以防止注射。但这足以保护这部分API吗?
在这种情况下是否可以使用强参数?
query_params.require(:only).permit(:id,:name)
不起作用,因为传递的字段是字符串,并且没有方法permit
。
答案 0 :(得分:2)
实际上,控制器不应该使用模型的实现细节。事实上,SQL的select中的值是以逗号分隔的,并且您的API按原样接受它是一个“巧合”,首先应该不依赖它。
我将向您介绍您可能会发现有用的工具,以便撰写您的解决方案。
# Array#&, set intersection
[1, 2, 3] & [2, 4, 1] # => [1, 2]
# Model.attributes
Model.attributes #=> ['id', 'name', ...]
# You can filter down the resulting array to produce a whitelist of columns
# Splat the array into the argument list
Model.select(*params[:only].split(',') & Model::SELECT_WHITELIST)
# ...the constant above has to be defined inside the model, obviously.
答案 1 :(得分:1)
您可以使用ActiveRecord::Base.sanitize
Model.select Model.sanitize(params[:only])