Rails Tutorialで学べることメモ-第9章-
Rails Tutorial を改めてしっかりやり直してのメモ第 9 章編
https://railstutorial.jp/chapters/advanced_login?version=7.0
便利なコマンド・メソッドなど
SecureRandom.urlsafe_base64
A–Z
, a–z
,0–9
, -
, _
のいずれかの文字(26×2+10+1+1=64 種類)からなる長さ 22 のランダムな文字列が返ってくる。
64 種類なので Base64 と呼ばれる。
このメソッドで生成される文字列は 64 種類から重複を許して 22 文字選ぶため、64^(22)分の 1 というとんでもなく小さい確率で衝突する。つまり、現実的には衝突しないと考えて良い。
assigns
テスト内部でassigns
という特殊なメソッドを使うと、インスタンス変数にアクセスできる。
例えば、あるコントローラーアクション内で@user
というインスタンス変数が設定されていた場合、assigns(:user)
でインスタンス変数にアクセスできる。
知識
cookies を盗む方法
大きく 4 つ紹介されている。それぞれの防ぎ方と共に整理する。
- 管理の甘いネットワークの通信をパケットアナライザで取得し、cookies 情報を取得する
- 通信内容を暗号化するために、TLS が有効な通信を行う
- DB に侵入し、保存されている記憶トークンを取得する
- 記憶トークンをハッシュ化して DB に保存する
- XSS 攻撃で取得する
- XSS が発生しないように注意する、Rails は自動でエスケープなどの対策を行う
- ログイン済みデバイスを窃盗または操作して取得する
- 根本的な対応はユーザーが気をつけるしかない
- 二次被害を抑える方法としては、別端末でログアウトされた場合に盗まれた端末でも再ログインが求められるようにするなど
インスタンスメソッドにするか、クラスメソッドにするか
一般に、あるメソッドがオブジェクトのインスタンスを必要としていない場合は、クラスメソッドにするのが常道
Rails でクラスメソッドを定義する記述方法は3通りある。
class User < ApplicationRecord
# 1. クラス名.メソッド名
def User.digest
...
end
# 2. self.メソッド名
def self.digest
...
end
# 3. class << self
class << self
def digest
...
end
end
end
Rails の cookies
cookies
はハッシュと同じように扱える。value
と一緒にオプションでexpires
を渡すことができる。
cookies[:remember_token] = { value: remember_token,
expires: 20.years.from_now.utc }
上記は 20 年後に有効期限切れになる(永続化の意図)ように cookies に記憶トークンを保存する。
この 20 年を有効期限とする設定はよく使われるため、Rails では同じ動作をするpermanent
メソッドが追加されたらしい。
cookies.permanent[:remember_token] = remember_token
三項演算子(ternary operator)
評価値 ? trueの時の式 : falseの時の式
という形式の記述方法。
ユーザーがremember_me
にチェックを入れていたら記憶トークンを発行、そうでなければ記憶トークンはない状態にする場合、次の 2 通りの記述は同じ意味になる。
if remember_me
remember(user)
else
forget(user)
end
remember_me ? remember(user) : forget(user)
わざと壊してテストする
テストがないと困るコードもあるが、そのテストを実装し忘れることがある。
テストがパスしないとコードがコミットできない仕組みは作れるが、テストがなくパスしていることに気づくのは難しい。
こういった場合、怪しい箇所にあえてraise
メソッドを仕込み壊してみる。
これで All Green だった場合、テストがないことになる。
まとめ
前の章で実装したログイン機構を発展させ、ブラウザを閉じても永続化できるログイン状態を実現する内容だった。
ログインを永続化させるにあたって、セキュリティリスクが上がるため、セッショントークンの設置や記憶トークンの扱いについて詳細に解説された。
本文中のコラムでさらっと
実際、Rails のエレガントな仕様の多くは、背後にある Ruby の高い拡張性によって実現されているのです。
とあり、Rails が黒魔術を産んでいると思っていたけど、産めるようにしたのは Ruby なんだよな、という当たり前のことに気がついた。