Rails

rails tutorial 7, 8 章の宿題

Controller側のStrong parameters

まずマスアサインメント機能を知る。

rails tutorial から

RailsではDBの更新系処理で複数のカラムを一括で指定できます。
例えば

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

など。

そしてこのユーザーからのリクエストはparams変数にHash として保存されるのである
この便利な機能をマスアサインメント機能と呼びます
しかし脆弱性として、想定してないカラムの更新がされてしまう場合がある
例えばadminカラムと言う管理者者権限を表すカラム。こちらが新しいユーザー登録の際に更新されてこの新しいユーザーに権限が更新されてしまう等。

rails3までの脆弱性への対策はModelがわのattr_accessibleで更新する値を管理するシステムをとっていた

rails4からのStrong paramers

# Never trust parameters from the scary internet, only allow the white list through.
def person_params
  params.require(:person).permit(:name, :age)
end

下記のように命名するのが慣例になっています。

def <Model名>_params
  params.require(:<Model名>).permit(:<カラム名1>, :<カラム名2>)
end

上の場合:personというモデルを必須ハッシュとして、それ以下の名前年齢カラム(属性)を許可し、それ以外は許可し内というコード

privateキーワード

最後にこのストロングパラメータが外部から使えないようにprivateキーワード下の処理となる様に

def create
  @person = Person.new(person_params)
  # 略
end

private

# Never trust parameters from the scary internet, only allow the white list through.
def person_params
  params.require(:person).permit(:name, :age)
end

SSL

SSL??なんぞや・・・

rails tutorialから
Secure Sockets Layer (SSL)これはローカルのサーバからネットワークに流れる前に、大事な情報を暗号化する技術

wikiから
SSL(Secure Sockets Layer)とTLS(Transport Layer Security)は、いずれもインターネット上でデータを暗号化して送受信する仕組み(プロトコル)です。 個人情報やクレジットカード情報などの重要なデータを暗号化して、サーバ~PC間での通信を安全に行なうことができます。

簡単にまとめると、通信を暗号化することで第三者による盗聴・改ざんを防ぎます。

2014年に大手検索サイトのGoogleは、ユーザが安全にサイトを閲覧できるようなユーザ保護の観点から、
SSL/TLS実装の有無を検索結果の基準の1つとすることを発表しました。
SSL/TLSを実装して安全性を考慮したウェブサイトが推奨されています。

とある様に、ウェブサイトの標準装備であると世界的な仕組み(プロトコル)である

SSL/TLSの役割

1,暗号化通信

「共通鍵暗号方式」と「公開鍵暗号方式」の両方を用いて、
インターネット上のデータ通信を暗号化することで第三者から盗聴を防ぎます。
サイトの大小にかかわらず、データの送信を行う場合には、
SSL/TLSを利用して通信の安全性を高めることが一般化しています。

2,サイト運営元の確認

SSL/TLS通信ではウェブサイト所有者の情報・送信情報の
暗号化に必要な鍵・証明書発行者の署名データ
(ネット上の実印のようなもの)を持つSSL証明書を利用します。
そのため、サービスの提供者が誰なのかを登録する必要があり
サービスの運営元が誰なのかをSSL証明書を通じて
利用者は確認をすることができます。

SSLの実装

・クライアント側
production.rbという本番環境の設定ファイルの1行を修正するだけで済みます。具体的には、configに「本番環境ではSSLを使うようにする」という設定をするだけです

config/environments/production.rb
 Rails.application.configure do
  .
  .
  .
  # Force all access to the app over SSL, use Strict-Transport-Security,
  # and use secure cookies.
  config.force_ssl = true
  .
  .
  .
end

・サーバー側(herokuの場合)
今現在開発サーバーとして使っているのはHerokuのデフォルトで、Rubyだけで実装されたWEBrickというもの
WEBrickは簡単にセットアップできたり動せることが特長ですが、著しいトラフィックを扱うことには適していません。つまり、WEBrickは本番環境として適切なWebサーバではありません

そこでPuma!!

rails5はデフォルトでPuma gemを使える様になっているので、HerokuのPumaのドキュメントに従って、設定を書き込んでいくことです

config/puma.rb
 workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  # Worker specific setup for Rails 4.1+
  # See: https://devcenter.heroku.com/articles/
  # deploying-rails-applications-with-the-puma-web-server#on-worker-boot
  ActiveRecord::Base.establish_connection
end

AND
Heroku上でPumaを走らせるファイルを作っておくだけ
name:Procfileはルートディレクトリ (Gemfileと同じディレクトリ) に置いておく必要がある

./Procfile
 web: bundle exec puma -C config/puma.rb

LAST
これで、本番環境用のWebサーバの設定は完了しました。これらの変更をコミットし、デプロイしてみましょう

$ rails test
$ git add -A
$ git commit -m "Use SSL and the Puma webserver in production"
$ git push
$ git push heroku
$ heroku run rails db:migrate

ユーザー登録フォームが無事に動いたら成功です。成功するとURLがhttps://に変わっていて、アドレスバーに鍵アイコンが表示されていることにも注目してください

SSL/TLSの確認方法

うえで生成された鍵アイコンをクリックすることでSSL証明書の情報をみることができる

SSL証明書の発行には、電子証明書の発行を認められた「認証局」による
運営元の認証作業を通過する必要があるため、SSL証明書を実装している
運営元のウェブサイトは、データの安全性と、運営元の信頼性をアピールでき

SSL/TLSの種類

1、Organization Validation SSL(企業実在認証SSL)

2,Domain Validation SSL(ドメイン認証SSL )

3,Extended Validation SSL(EV SSL)

それぞれ値段や確認項目がちがうので詳細はしらべて

flash

flashとはなんぞや...

・常識的に備わっている機能で、特殊な変数を使い、ハッシュのように扱う

・ログイン時のウェルカムメッセージや、項目追加の成功通知など、ユーザに簡単な通知を行いたい時に利用する。

・コントローラでflashメッセージを設定し、ビューで表示する。

flashは全体で見ればHash。あるキーに対する値としてメッセージを設定する。キーは自由に設定できるが、デフォルトとしてalertとnoticeがある。

・設定したメッセージは、sessionに保存される。つまり、flashは、sessionを利用した機能の1つ。

・普通のセッション変数では破棄するまで値は保持されるが、flash の場合は一度表示されるとアクション終了時に自動的に消去される。

flashの使い方

1,コントローラ側で定義

2,ビューで表示

(1)flash[:notice] = "hogehoge"

(2)<%= flash[:alert] %> → ”hogehoge”


(1)flash[:success] = "Welcome to the Sample App!"

(2)<% flash.each do |message_type, message| %>

redirect_toのオプションとして

下の様にもかける
redirect_to :root, :flash => {:error => "errorが起きました"}

デフォルトのnoticeとalertは、
例えば、redirect_toのときは、下記のように書ける。

redirect_to :root, :notice => "hello"
redirect_to :root, :alert => "errorが起きました"

flashの種類

flash

・一度表示されるまで値が保持される。
そのため、予期しないメッセージを表示してしまうことがあるので注意。
・そのアクション自体か、リダイレクトした次のアクションで利用。
・一度表示された時点で破棄される。

flash.now

・定義したメソッド内(同じリクエスト内)でのみ有効。
・メソッド1で定義した場合、メソッド2では利用不可。
・redirectさせた先では表示されない。

flash.keep

・普通flashは一度表示されると消えるが、flash.keepで設定すれば、値を保持し続ける。
・引数なしで .keep を指定すればすべての flash が保持される。

Session

なにかを説明する前に知っておくべきことがあるのでで下にまとめる

HTTPはステートレスプロトコル

かんたんにまとめると
「文字通り「状態 (state)」が「ない (less)」ので、HTTPのリクエスト1つ1つは、それより前のリクエストの情報をまったく利用できない、独立したトランザクションとして扱われ、言ってみれば、リクエストが終わると何もかも忘れて次回最初からやり直す健忘症的なプロトコル」

その為ユーザーのIDを保持しておく手段がHTTP内にまったくないのである

cookies

ユーザーのブラウザに保存される小さなテキストデータです。cookiesは、あるページから別のページに移動した時にも破棄されないので、ここにユーザーIDなどの情報を保存できます
アプリケーションはcookies内のデータを使って、例えばログイン中のユーザーが所有する情報をデータベースから取り出すことができます

一時セッション

Railsメソッドのsessionを使って作成します。この一時セッションは、ブラウザを閉じると自動的に終了します

RESTfulなセッションを作っていこう

以上のことからセッションをRESTfulなリソースとしてモデリングできると、
1,ログインページではnewで新しいセッションを出力し、
2,そのページでログインするとcreateでセッションを実際に作成して保存し、
3,ログアウトするとdestroyでセッションを破棄する、
といった機能にできる

そこで注意するべき点として

UsersリソースではバックエンドでUserモデルを介してデータベース上の永続的データにアクセスするのに対し、Sessionリソースでは代わりにcookiesを保存場所として使う

こと。肝に銘じてすすむ。

Sessionsコントローラ(8.1.1)

ログインとログアウトの要素を、Sessionsコントローラの特定のRESTアクションにそれぞれ対応付けることにします

$ rails generate controller Sessions new

image.png
↑理想モックアップ

config/routes.rb
 Rails.application.routes.draw do
  root   'static_pages#home'
  get    '/help',    to: 'static_pages#help'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  get    '/login',   to: 'sessions#new' #①
  post   '/login',   to: 'sessions#create'#①
  delete '/logout',  to: 'sessions#destroy'#①
  resources :users
end

・①必要な名前付きルートを作成
・rails g で出来た不要なルートは削除
・/loginルーティングでGETとPOST 2通りあるのに注目

test/controllers/sessions_controller_test.rb
 require 'test_helper'

class SessionsControllerTest < ActionDispatch::IntegrationTest

  test "should get new" do
    get login_path
    assert_response :success
  end
end

・Sessionsコントローラのテストで名前付きルートを使うようにする

・GET login_pathとPOST login_pathとの違いを説明できますか?