Rails에서 검색 기능을 직접 구현하는 방법

8692 단어 MySQL찾다formRails

입문


이전에 썼던 것을 아래에서 계속해라.
Rails의 routing에서 scope/namespace/module의 차이 - Qiita
이번에는 gm를 사용하지 않고 간단한 검색 기능을 만드는 방법을 적겠습니다.

환경

  • macOS HighSierra 10.13.6
  • Rails 5.2.0
  • Ruby 2.5.1
  • mysql 5.7.22
  • docker에서 mysql
  • 만들기
  • Docker version 18.03.1-ce
  • 검색 기능 개요

  • 양식에 검색 키워드(문자열) 입력
  • 창의 검색 키워드(문자열)를 매개 변수로 컨트롤러 → 모델
  • 에 전달
  • 매개 변수로 전달된 문자열을 MySQL로 모호하게 검색SELECT ??? FROM table WHERE LIKE '%文字列%'
  • 검색 결과 보기
  • 측면 구현 보기


    먼저 보기에서 검색할 수 있는 폼을 설정합니다.
    app/views/top/index.html.erb
    ・・・
    <h2>検索</h2>
    <%= form_tag(root_path, method: :get) do %>
      <%= text_field_tag :search %>
      <%= submit_tag 'Search', name: nil %>
    <% end %>
    ・・・
    
    하나하나 설명하다.
    form_tag는 ActionView:Helpers를 계승하여 검색 입력 폼을 간단하게 만들 수 있는 조수 중 하나입니다.form_tag는 2개의 매개 변수를 가져와 검색 결과를 표시하는 URL(이번 경로 지정)과 매개 변수로 보내는 HTTP 방법(GET)을 지정합니다.
    text_field_tag도 조수 중의 하나입니다.다음 HTML을 렌더링하는 중입니다.
    <input type="text" name="search" id="search">
    
    submit_tag도 조수입니다. 입력 단추입니다.name는 하나의 표지부호이기 때문에submit 단추nil가 여러 개 없으면 됩니다.
    참조: Tips-Rails Webook은 Rails의 양식에 여러 개의 제출 단추를 배치합니다.

    이때 검색하면...


    범위를 좁힐 수는 없지만 입력 폼에 "test"를 입력하고 제출하면

    의 출력입니다. 로그는 다음과 같습니다.
    Started GET "/?utf8=%E2%9C%93&search=test" for 127.0.0.1 at 2019-03-24 06:52:27 +0900
    Processing by TopController#index as HTML
      Parameters: {"utf8"=>"✓", "search"=>"test"}
      Rendering top/index.html.erb within layouts/application
      Article Load (3.8ms)  SELECT `articles`.* FROM `articles`
      ↳ app/views/top/index.html.erb:10
      Rendered top/index.html.erb within layouts/application (15.6ms)
    Completed 200 OK in 40ms (Views: 32.6ms | ActiveRecord: 3.8ms)
    
    지정한 대로 GET 매개변수에 문자열search이 전달됩니다.다음에는 Controller와 Model로 받아서 처리하세요.

    컨트롤러 측 설치

    test.이렇게 하면 보기 폼에서 포획한 파라미터를 모델에 전달할 수 있습니다.
    app/controllers/top_controller.rb
    class TopController < ApplicationController
      def index
        @articles = Article.all.search(params[:search])
      end
    end
    
    .search(params[:search]) 방법은 자제 방법이다.계속 이렇게 하면 오류가 발생합니다.search.따라서 Model에서 메서드를 작성합니다.

    모델 측면 설치


    app/models/article.rb
    class Article < ApplicationRecord
      def self.search(search)
        search ? where('title LIKE ?', "%#{search}%") : all
      end
    end
    
    클래스 방법은 자신의 값을 되돌려주기 때문이다.
    그럼 표에서'title1'을 검색해 보세요.

    로그에서 SQL을 확인할 수 있습니다.
    SELECT `articles`.* FROM `articles` WHERE (title LIKE '%title 1%')
    
    SQL에서 알 수 있듯이 제목 열에서 특정 문자열NoMethodError이 포함된 데이터를 모호하게 검색했습니다(와일드카드를 사용하여 부분적으로 일치하는 검색).

    레일스의 안전 대책은


    DB를 조작할 때 SQL을 직접 조립하면 SQL이 주입될 가능성이 있습니다.
    예를 들어 다음과 같이 쓸 수도 있다
    app/models/article.rb
    class Article < ApplicationRecord
      def self.search(search)
        search ? where("title='#{search}'") : all
      end
    end
    
    이 경우 검색 양식에서
    '); select * from articles;--('
    
    submit을 쓴 후 뱉은 로그는 다음과 같습니다.
    SELECT `articles`.* FROM `articles` WHERE (title='');
    select * from articles;
    --('')
    
    이 작업을 MySQL에서 수행하면 두 번째 행의 SELECT 문이 정상적으로 수행됩니다.이렇게 되면 title 1 (표 삭제 명령) 이렇게 할 수 없는 명령을 실행할 수도 있다.
    그래서DROP TABLE articles; where('title LIKE ?', "%#{search}%") 이러한 SQL 자리 차지 문자의 기능은 SQL 문법을 결정한 후 파라미터의 문자열 전개 등이 발생하게 되는데, 그 결과 파라미터?의 데이터로부터 의미를 바꾸어 SQL 주입을 방지하는 방법은 이미 습관이 되었다.
    이번에는 여기까지!

    참고 자료

  • [Rails 입문] form_사무라이 블로그(Samurai Blog) - 프로그래밍 입문자를 위한 사이트
  • Rails에서 보안을 고려하지 않고 만든 웹 응용 프로그램에 취약성이 있는지 여부(취약성 검증편)-남녀 비율은 카레와 복신포밥과 차이가 많지 않다
  • SQL 주입 - Qiita를 고려하여 선택할 열을 동적으로 변경합니다.
  • 좋은 웹페이지 즐겨찾기