원시 SQL을 사용하는 경우 ActiveRecord에서 수동으로 값을 이스케이프 처리하는 방법이 있습니까? 이 같은레일스에서 값을 이스케이프 처리 (mysql_real_escape_string()과 유사)
뭔가 좋은 것 : 당신은 여전히 물음표 이스케이프 값로 서 양식을 사용할 수 있습니다
self.escape("O'Malley") # O\'Malley
원시 SQL을 사용하는 경우 ActiveRecord에서 수동으로 값을 이스케이프 처리하는 방법이 있습니까? 이 같은레일스에서 값을 이스케이프 처리 (mysql_real_escape_string()과 유사)
뭔가 좋은 것 : 당신은 여전히 물음표 이스케이프 값로 서 양식을 사용할 수 있습니다
self.escape("O'Malley") # O\'Malley
당신은 할 수 있습니다 :
Dude.sanitize("O'Malley")
또는
Dude.connection.quote("O'Malley")
같은 결과 두 가지 모두의 경우 누군가에 => "'O''Malley'"
에도 Model.find_by_sql
와 함께.
단순히 제 소자 쿼리 인 배열을 전달하고 후속 요소로 치환 될 수있는 값이다
예 레일 API 문서에서 :.
Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
을 반환 삽입하면 어떨까요? –
나는 그것을 파헤 칠 수 있지만 실제로 : 왜 ActiveRelation/ActiveModel 외부에 삽입하고 있습니까? –
나는 INSERT IGNORE를하고 있는데 성능을 위해 한 문장으로 여러 레코드를 업데이트하고있다. –
쉽게 mysql2를 사용 보석이 작업을 수행합니다 :
irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'mysql2'
=> true
irb(main):004:0> Mysql2::Client.escape("O'Malley") # => "O\\'Malley"
=> "O\\'Malley"
또는 경우 이전 MySQL을 사용 (하지 mysql2) 보석 :
irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'mysql'
=> true
irb(main):004:0> Mysql.escape_string("O'Malley")
=> "O\\'Malley"
이렇게하면 원하는 모든 것을 이스케이프 처리하여 데이터베이스에 삽입 할 수 있습니다. sanitize 메소드를 사용하여 레일즈 애플리케이션의 대부분의 모델에서도이 작업을 수행 할 수 있습니다. 예를 들어 Person이라는 모델이 있다고 가정 해보십시오. 너는 할 수있어.
Person.sanitize("O'Malley")
그 트릭을 수행해야합니다.
는 액티브 소스에 빠른 다이빙은 SQL 문의 [string, bind_variable[, bind_variable]]
유형을 살균위한 방법 "sanitize_sql_array"을 보여
당신은 직접 호출 할 수 있습니다
이sql = ActiveRecord::Base.send(:sanitize_sql_array, ["insert into foo (bar, baz) values (?, ?), (?, ?)", 'a', 'b', 'c', 'd'])
res = ActiveRecord::Base.connection.execute(sql)
제이슨 : 이것은 DB 독립적이기 때문에 더 나은 해결책입니다. 앱이 Heroku에 배포 된 경우 현재 허용되는 솔루션 (@quest)이 작동하지 않습니다. –
4 년 후'sanitize_sql_array'와 그 사촌들은 여전히 공개 API의 일부가 아닙니다. 편리한 공공 시설이 있습니까? –
는 @의 jemminger의 솔루션에 대한보다 구체적인 예를 찾고, 여기가 대량 삽입입니다 : 여기
users_places = []
users_values = []
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
params[:users].each do |user|
users_places "(?,?,?,?)"
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은 "그들이 당신을 내버려 두지 않게하십시오"는 "돈을 버려서는 안된다"고 할 것입니다. 당신은 당신이 @konus에 의해 게시 솔루션을 사용할 때 발생하는 귀하의 문자열을 포장 여분의 작은 따옴표를 원하지 않는 경우
, 당신은이 작업을 수행 할 수 있습니다
는Dude.connection.quote_string("O'Malley")
이 "O\'Malley"
대신 "'O\'Malley'"
의
이렇게하면 SQL에서 벗어날 수 있습니다. 주입. – tvdeyen
@ tvdeyen : 특히 위의 답변에 비해 위의 사항이 어떤 방식으로 취약한지를 설명해 주시겠습니까? 궁극적으로,'quote_string'는 사용중인 특정 ActiveRecord 어댑터에 의존하게 될 것입니다. mysql2 어댑터와 추상 mysql 어댑터의 경우, quote는 문자열 값에 대해'quote_string'을 호출하고 결과를 따옴표로 묶습니다. 어떤 멀티 바이트 주입이나 다른 것을 생각하고 있습니까? 고맙습니다. – Nathan
고마워요 @ 네이선., 그것은 나를 위해 작동 .. –
나는 당신의 모델 이름을 좋아합니다. '야, 너 멋지다. –
@NateSymer : 예, 글쎄, 그건 당신 생각과 같습니다. – Fuser97381
다른 사람이 궁금해하는 경우에는 네, 정확히 동일합니다 : [sanitize calls connection.quote] (http://apidock.com/rails/ActiveRecord/Base/sanitize/class) – mltsy