2012-06-01 3 views
1

SQL 인젝션 공격의 위험없이 어떻게해야합니까?ActiveRecord에서 안전한 방법으로 매개 변수를 삽입하는 방법

nearest = Site.minimum(['abs(latitude - ?) - abs(longitude - ?)', params[:lat], params[:lon]], group: :id) 

을하지만 그것은 작동하지 않습니다

nearest = Site.minimum('abs(latitude - ' + params[:lat] + ') - abs(longitude - ' + params[:lon] + ')', group: :id) 

나는 시도했습니다. 이 문서는 이것을 달성하는 방법이 명확하지 않습니다.

미리 감사드립니다.

+0

[이 Rails API] (http://api.rubyonrails.org/classes/ActiveRecord/Base.html)에 따르면 당신이 작성한 두 번째 방법은 안전한 방법입니다. 그것은 어때? – MrDanA

+0

두 번째 방법은 배열을 볼 때 열 이름을 필요로하기 때문에 작동하지 않습니다. 이 구문은 when() 및 : conditions => –

+0

에서만 작동합니다. SQL 함수를 사용하면 레일 빌더가 고장납니다. Squeel은 SQL 함수를보다 잘 지원합니다 : https://github.com/ernie/squeel (또는 railscast : http://railscasts.com/episodes/354-squeel) – DGM

답변

1

레일즈는 내부적으로 자리 표시자를 처리하기 위해 sanitize_sql_for_conditions을 사용합니다. 물론,이 메소드는 보호되어 있으므로 ActiveRecord 모델 외부에서 (깔끔하게) 사용할 수는 없습니다.

nearest = Site.minimum(
    Site.send(:sanitize_sql_for_conditions, [ 
     'abs(latitude - ?) - abs(longitude - ?)', 
     params[:lat].to_f, params[:lon].to_f 
    ] 
) 

아니면 속임수없이 sanitize_sql_for_conditions를 사용하도록 허용 할 것 그래서 당신은 Site 클래스 메소드 내에서 그 논리를 넣을 수 있습니다 : 당신은 send를 사용하여 protectedness 주위에 얻을 수에 다음

class Site < ActiveRecord::Base 
    def self.whatever_this_is(lat, lon) 
     minimum(
      sanitize_sql([ 
       'abs(latitude - ?) - abs(longitude - ?)', 
       lat, lon 
      ]) 
     ) 
    end 
end 

과 귀하의 컨트롤러 :

nearest = Site.whatever_this_is(params[:lat].to_f, params[:lon].to_f) 

to_f 호출에 유의하십시오. 당신이 사람들을 포함하지 않는 경우 params[:lat]params[:lon]는 문자열되며 sanitize_sql_for_conditions 같은 그들을 인용합니다 :

abs(latitude - '11.23') - abs(longitude - '42.6') 

데이터베이스 수도 있고 당신이 그렇게 숫자에서 문자열을 빼기 위해 노력보고 행복하지 않을 수 있습니다 자신이 의미하는 바를 정확하게 말하고 유형 변환을 직접하는 것이 가장 좋습니다.

+0

감사합니다. 나는 이것을 위해 정착했다 : c = ActiveRecord :: Base.connection; 가장 가까운 Site.select ('ABS (위도 -'+ c.quote (params [: lat]) + ') - abs (경도 -'+ c.quote (params [: lon]) + ') AS 거리, id ') .order (: distance) .limit (1) –

0

허용 위 예제에서 수행하려는 작업을 알 수는 없지만 첫 번째 인수로 메서드 이름을 사용하는 최소 메서드를 잘못 사용하고있는 것처럼 보입니다. 당신이 그것에 조건을 추가하려면

Site.minimum(:latitude) 

, 당신이 사용하고자하는 것이라고 생각 :

Site.where(country: 'USA').group(:id).minimum(:latitude) 

다시 말하지만,이 예제는 당신이 기대하는 결과를 반환하지 않습니다 만, 예를 들어, API가 어떻게 사용되는지 더 잘 설명해야합니다.

관련 문제