6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2021年8月23日 現場Rails Chapter6-7 (p.253~258) セキュリティを強化する

Railsの代表的なセキュリティ機能

  • StrongParameters
  • CSRF対策
  • インジェクション対策

Strong Prametersとは

想定通りのパラメータかどうかをホワイトリスト方式(リストにないアプリケーションやプログラムは起動しないよう制限を設け、リストにあるアプリケーションやプログラムのみを実行します。 リストに入っていないものはブロックし、一切使用しないことで危険性を回避する)でチェックする機能。 ホワイトリストブラックリストの逆のものというイメージを持つ。

マスアサイメント機能とは

マスアサイメント機能とは、モデルからインスタンスを生成するときに、インスタンスに複数の属性を一括代入できる機能です。 ざっくり言うと、複数のキーワード引数に値を渡すこと。登録、更新を一括でできてしまう機能をマスアサイメント機能という。 つまり、登録更新処理またはインスタンス生成時(newする時)どちらでも属性を一括代入できる。

  Person.new(name: 'hoge', age: 24)
  person.update(name: 'hoge', age: 24)

DBにないカラムをnewの引数で指定すると、エラーが起こる。

以下の例の場合、Taskオブジェクトを生成する際に、nameとdescriptionという2つの属性に値を一括で代入している。

  task = Task.new(name: 'ラーメン食べたい', description: '今すぐ食べたい')

許可される型

Railsガイド Action Controllerの概要 4.5.1 許可済みスカラー値より

params.permit(:id)

  • String
  • Symbol
  • NilClass
  • Numeric
  • TrueClass
  • FalseClass
  • Date
  • Time
  • DateTime
  • StringIO
  • IOActionDispatch::Http::UploadedFile
  • Rack::Test::UploadedFile

「paramsの値には許可されたスカラー値の配列を使わなければならない」=>以下のようにキーに空の配列を対応付けられる params.permit(id: [])

Strong parametersの基本構文

#controller内定義
private
def user_params
  params.require(:キー(モデル名)).permit(:カラム名1,:カラム名2,・・・).merge(カラム名: 入力データ)
end

requireメソッド

params内の特定のキーに紐付く値だけを抽出する事ができます。そのため、引数には取り出したい値のキーを指定する必要があります。requireに設定した値が見つからない場合は、例外を発生させます。

#キー値userに対するデータを抽出したい場合
params.require(:user).permit(・・・略・・・)

permitメソッド

許可された値のみを取得することができます。  そのため、permitメソッドの引数には登録を許可する全てのカラム名を指定しておく必要があります。もし、許可されいないカラムがparams内に存在した場合、そのデータは取得されず無視されます。

#Userモデルに存在するnameおよび、emailカラムのみ入力を受け付けたい場合(他のカラム(admin)は受け付けないたくない)
params.require(:user).permit(:name,:email)

mergeメソッド

mergeメソッドを使用することでハッシュ同士を結合することができます。 例えば、paramsに含まれない値をストロングメソッドに加えたい場合などに、ストロングパラメータの後に記述することができます。

#paramsのkeyとvalueに含まれていないものを追加したい場合、mergeを使う
  params.require(:user).permit(:name,:email).merge(user_id: current_user.id)

↓チェリー本 P163 mergeの例文

h = { us: 'dollar', india: 'rupee'}
{ japan: 'yen' }.merge(h) #=> {:japan=>"yen", :us=>"dollar", :india=>"rupee"}

一次元ハッシュと2次元ハッシュ

#1次元ハッシュ
{key1: value1, key2: value2}

#2次元ハッシュ
{key1: value1, key2: {key3: value3}}

#一次元ハッシュの場合=>URL
params.permit(:キー名)

# 二次元ハッシュの場合=>モデル
params.require(:モデル名).permit(:キー名)

requireとpermitメソッドとmergeメソッドのめっちゃわかりやすい例↓

#keyであるboardのvalueをハッシュの形で指定している。mergeで追加されるのは、boardのvalueの部分。
params.require(:board).permit(:body).merge(user_id: current_user.id)

{"body"=>"abc", "user_id"=>5} 

#=>{board:{body: value1, user_id: value2}} 

privateメソッド

privateメソッド配下に記述したメソッドは、クラス外からのアクセスができません。  基本的にストロングパラメータは、クラス外からのアクセスをさせないようにprivateメソッド配下に書く。

CSRF

  • CSRFとは、ユーザーがログイン済みのアプリケーションに対して、悪意のあるリクエストを飛ばすこと。

  • RailsにおけるCSRF対策はHTTPメソッドのGET以外を使用することで、自動的にパラメーターにセキュリティートークンを持たせることで実現している。

CSRF攻撃例

攻撃例: Amazon会員の太郎さん。ブラウザ操作でログアウトしていない状況で、悪意あるサイトにアクセスしました。

そこには「こちらをクリックすると懸賞にワンクリックで応募できます」の文字と、ボタンがあり、太郎さんはそのボタンをクリックしました。

しかし、そのボタンはAmazon会員を解約するhref="...../delete"みたいなURLが仕込まれており、太郎さんは意図せずAmazon会員を解約してしまいました。

Ajax

JavaScriptの値を明示的にRails側に渡したい場合は、jQueryajaxメソッドを使用するのが良い。(jQuery.ajax())ただし、jQueryrails-ujsの前に読み込んでおく必要がある。 - 「Rails.ajax()」関数を利用することでトークン付きのAjaxリクエストを行うことが出来る。

Ajaxとは?

JavaScriptでサーバー側との通信を「非同期」で行い、通信結果によって「動的にページの一部だけ書き換える手法のこと」です。JavaScript以外にもXMLやDOMなど「既存の機能」を組み合わせて実現します。

例)twitterのいいね機能 ページ全体の更新を行うのではなく、読み込みたい部分だけの通信を行うことで、いいね部分だけ更新することができる。通信の無駄がない!対して、同期通信は更新をしなくて良い部分も更新してしまうので無駄が多い!

POSTリクエス

Railsのルーティングの文脈での「DELETE」「PATCH」「PUT」なども、ここでいうPOSTリクエストに該当します。

参照

Railsガイド StrobngParameters https://railsguides.jp/action_controller_overview.html#strong-parameters

Rails】requireとpermitメソッド https://qiita.com/morikuma709/items/2dc20d922409ae7ce216

Ruby on Rails】ストロングパラメータって何なの?

https://qiita.com/ozackiee/items/f100fd51f4839b3fdca8

チェリー本p163

pikawakaさんブログ https://pikawaka.com/rails/permit

Railsのセッション管理には何が最適か https://qiita.com/shota_matsukawa_ga/items/a21c5cf49a1de6c9561a

初心者目線でAjaxの説明 https://qiita.com/hisamura333/items/e3ea6ae549eb09b7efb9

Railsガイド 「Rails セキュリティガイド -クロスサイトリクエストフォージェリ (CSRF)-」 https://railsguides.jp/security.html#%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%AA-csrf

Railsのセッション管理には何が最適か https://qiita.com/shota_matsukawa_ga/items/a21c5cf49a1de6c9561a