2011-08-22 2 views
16

레일에서 SQL을 살균하는 방법이 있습니까 find_by_sql?레일, find_by_sql에서 SQL을 살균하는 방법

나는이 솔루션을 시도했다 : Ruby on Rails: How to sanitize a string for SQL when not using find?

을하지만

Model.execute_sql("Update users set active = 0 where id = 2") 

그것은 오류가 발생합니다에 실패하지만, SQL 코드가 실행되고 ID 2를 가진 사용자는 이제 비활성화 된 계정이 있습니다. 또한

간단한 find_by_sql이 작동하지 않습니다

Model.find_by_sql("UPDATE user set active = 0 where id = 1") 
# => code executed, user with id 1 have now ban 

편집 :

글쎄, 몇 가지 복잡한 쿼리를 만들기 위해 관리자 패널에서 (SQL에 의해 선택) 해당 기능을하도록 요청 내 클라이언트 (조인, 특수 조건 등). 그래서 find_by_sql을 원합니다.

두 번째 편집 : 나는 '악'SQL 코드가 실행되지 않습니다 달성하고자하는

.

관리자 패널에서 query ->Update users set admin = true where id = 232을 입력하면 UPDATE/DROP/ALTER SQL 명령을 차단하고 싶습니다. 그냥 알고 싶다면 여기서 SELECT를 실행하면됩니다.

일부 시도 후에 나는 결론을 내리고 sanitize_sql_array 불행히도하지 마십시오.

레일에서이를 수행 할 방법이 있습니까 ?? 혼란을 드려 죄송합니다

..

답변

13

이 시도 :

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

당신은 변수에 저장하고 목적을 위해 사용할 수 있습니다.

+0

결과에서 발견 ([, PARAMS? "WHERE (이름은 =) 사용자가 SELECT * FROM"]) :'보호 방법 액티브 :: 자료 요구 'sanitize_sql_array'Class' –

+1

내 게시물을 업데이트했습니다. – bor1s

+0

.. 또는 이것을 사용할 수 있기를 바랍니다. ActiveRecord :: Base.send (: sanitize_sql_array, "your string")' – bor1s

9

이니셜 라이저에 넣을 수있는 작은 스 니펫을 만들었습니다.

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

을 그리고 당신은 쿼리 당신이 원하는 방식으로 호출 할 수 있습니다 :

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

지금 당신이 당신의 쿼리를 탈출 할 수

users = User.find_by_sql(query) 
+2

이 작업은 가능하지만 머리를 위로 올리면됩니다. , "보내기"가 필요하지 않습니다. 호출자가 같은 클래스 인 경우 보호 된 메서드 호출은 수신기에서 허용됩니다. 즉, 메소드 정의 만 필요합니다. "def self.escape_sql (obj); sanitize_sql_array obj; end;" (SO가 주석 반환 줄 허용 이후 사용 된 세미콜론) –

+0

[원숭이 패치에 대한 대안과 관련이 있음을 알게되었습니다] (https://stackoverflow.com/a/2329394/673826) – mlt

+0

추가 및 예제 제공 주셔서 감사합니다 그것을 사용하는 방법에. –

8

약간 더 범용 :

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

여분의 대괄호없이 array 절을 사용하여 where 절을 입력하는 것처럼 호출 할 수 있습니까? 또는 해시 스타일 보간법.

+0

감사합니다. 이것은 완벽하게 작동했습니다. 이것이 이니셜 라이저에 추가되었다고 덧붙입니다. – KPheasey

1

이 예제는 INSERT 쿼리에 대한 것이지만 UPDATE 쿼리에 대해서도 비슷한 접근법을 사용할 수 있습니다.원시 SQL의 대량 삽입 : 여기

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 

그것은 문자열에 작은 따옴표를 이스케이프 적절한 쿼리 문자열을 생성의 reference to sanitize_sql_array method in ActiveRecord::Base입니다. 예를 들어 punch_line은 "그들이 당신을 내버려 두지 않게하십시오"는 "돈을 버려서는 안된다"고 할 것입니다.

관련 문제