rails 独学して軽くにちゃんまとめつくる

インターン中大学生のブログ

ぐるぐる回って何をしたいのかが変わってく。今はマッチングサイトを作りたい、もしくは論文のキュレーションサイトかな。

rails tutorial 8章のセキュリティーについてまとめ

この8章ではセキュリティーのことをどっぷりするので知らない単語がどんどんでてきたので注意。

 

 

1回目  11/26&11/27

さっぱりわからなかった。後半1/4は5秒で読み終えた。昨日は8.1から8.2を読み通すのに1時間30分かかった。あきらかに時間の無駄だ。27にとりあえず8.3を読み終えて力尽きた。これから9章に進む。

疑問点と習ったことをメモしておいて次へと進む。

疑問 ①②

わかったこと: セッションとクッキー、digestとbasic

 

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

セッションとクッキー

 

セッション:

セッションコントローラーを作ったことからわかるように、サーバー(自分)側で管理するもの。

 

クッキー:

クライアント(相手)側で管理するもの。自分のブラウザでも確認できるようになっている。

http://so-zou.jp/web-app/tech/browser/functions/cookie/

 

僕たちがtutorialでごちゃごちゃしているのはセッションだということを意識する。

セッションは宝箱でクッキーは秘密のカギ。大事なものはセッションで管理するが、他人に開けられないように自分だけがクッキーとして保管しておく。

Usersリソースと異なるのは、UsersリソースではバックエンドでUserモデルを介してデータベース上の永続的データにアクセスするのに対し、Sessionリソースでは代わりにcookiesを保存場所として使用する点です。ログインのしくみの大半は、cookiesを使用した認証メカニズムによって構築されています。

--rails tutorial

 

ログインと新規登録は違うことを頭にいれておく。

セッションフォームとユーザー登録フォームの最大の違いは、セッションにはSessionモデルというものがなく、そのため@userのようなインスタンス変数に相当するものもない点です。

 

 

これも読むとわかりやすいかも。

 セッションとクッキーの違い - エンジニアだけどブログを始めてみた

Didgest認証とBASIC認証

この記事ではBASIC認証の危険性を実験しています。こちらの方の例ではbase64という方式を採用しています(rails tutorialでもでてきた)。

これは簡単に暗号化された文字列をもとの文字列に変換することができます。

この例では「guest:Take5」をハッシュ化して「Z3Vlc3Q6VGFrZTU」文字列にしてますが

http://hogehoge.tk/tool/

このサイトで一発でもとに変換できます。

それじゃあまずいということでdigest認証の出番。これはサーバー側からnonceというでたらめな文字列が送られる。このnonceとクライアント側が設定したpasswordをこねくりまわしてハッシュ化するからより安全になる。

 

 

③セッションは2つ作ってる

8.2まででブラウザを閉じると消えてしまうセッションを作って、8.4では20年続くセッションを作っている。

 

 

④form_forのつかいかた

Railsでは上のように書くだけで、「フォームのactionは/usersというURLへのPOSTである」と自動的に判定しますが、セッションの場合はリソースの名前とそれに対応するURLを具体的に指定する必要があります3

 と書いてあるが、正確にはルーティングのときresoursesでルートを定義したときのみ

form_for(@users) という書き方ができる

 

⑤ヘルパーをコントローラーでつかうとき

ビューではふつうに関数名をうちこむだけで使えるが、コントローラーでつかうときは使いたいコントローラーでincludeしなければならない。すべてのコントローラーで使いたいときはapplication_controllerでincludeリスト8.11

 

 

⑥ クッキーに代入

session[:user_id] = user.id

これをすると、ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成されます。この後のページで、session[:user_id]を使用してユーザーIDを元通りに取り出すことができます。一方、cookiesメソッド (8.4) とは対照的に、sessionメソッドで作成された一時cookiesは、ブラウザを閉じた瞬間に有効期限が終了します。

 こうやってクッキーに代入してたのか。このコマンドをlog_inメソッドとしてヘルパーに書き、それをapplicationでincludeした。このlog_idメソッドはログインが成功したときに使われる。(リスト8.13)

 

⑦findとfind_byの使い分け

findは主キーをさがしだしなければ例外が発生するので、ないことがわかっている状況(ユーザー検索など)ではfind_byを利用する。

 

⑧リンク移動の略記法

 

renderやlink_toでこういうのがあるので混乱しないように。

<%= link_to "Profile", current_user  %>

<%= link_to "Profile", user_path(current_user) %>

 

⑨digestはuser.rbで定義する

内容はわからなくてもいいが、これは引数をでたらめな文字列に変化することのできるメソッド。

 

⑩テストではヘルパーは呼び出せない。

テストのときはそれ専用のtest_helperがあり、そこのヘルパーしか呼び出せない。だからsession_helperのcurrent_helperは呼び出せないんだとさ。8.23

 

⑪ログアウトの記述は簡単

def  log_out

  session.delete(:user_id)

 @current_user = nil

end

これをヘルパーで宣言して、sessionコントローラーで呼び出すだけ。あっけない。

 

⑪記憶トークンとダイジェストで永続的cookie??

 サーバーで保存するのは記憶トークンのハッシュ値(remember_digest)。ダイジェストと呼んでいる。

クライアントで保存するのはremember_token と user_idのハッシュ値

 

 ⑫8.2.1のわかりにくさ

 ログイン機能をつけたといってるが、ぼくたちの知っているログイン機能までたどりついてないのがわかりにくい原因。ログイン前後で変化がないのでわかりにくい。現段階ではログインしたからといって見えないページが見えたり、自分の名前がみえたりしない。ログインしてないからといって使えないページがあるわけではない。これから実装していくのだ。

その後、login や longin? メソッドを作るが、こいつらがログイン前後の判断をしてくれる要。

user = User.find_by(email: params[:session][:email].downcase)
これも大事なやつの1つ。ログインフォームで受け取ったメルアドをもとに、モデルにあるデータからメルアドをもとにユーザーが登録されているか探す。

 

⑬セッションと名乗るのが2つある

1つはコントラーラーでやくっているもの params[:session][:use_id]とかいてあるもの

もう一つはsession[: use_id]とかいてあるもの。

前者はログイン画面で値を受け取る機能がある

後者はクライアントにセッションとして保存するための機能。

2つは違うことを頭に入れておかなければこんがらがってしまう。

 

 

⑭8.4のむずかしさ

整理 
「永続的cookies」
「記憶トークン」:リスト8.31
「記憶ダイジェスト」:記憶トークンをダイジェストにしてモデルに保存する

ここではクライアントのサーバーにクッキーとして保存するからセキュリティ対策のためにしていることがある。

①7.5でsslを有効にした
②記憶トークンのハッシュ値を保存する
③ログアウトしたときにトークンの値を変更し、ブラウザを表示するときに署名化(コラム8.2の下のほう)

 

 

  1. 記憶トークンにはランダムな文字列を生成して用いる。
  2. ブラウザのcookiesにトークンを保存するときには、有効期限を設定する。(8.4.2)
  3. トークンはハッシュ値に変換してからデータベースに保存する。
  4. ブラウザのcookiesに保存するユーザーIDは暗号化しておく。(コラム8.2のしたのほう)
  5. 永続ユーザーIDを含むcookiesを受け取ったら、そのIDでデータベースを検索し、記憶トークンのcookiesがデータベース内のハッシュ値と一致することを確認する。

 

User.find_by(id: cookies.signed[:user_id])これで取り出す。

 

 

 

疑問

sessin[:user_id]ってなんだ

 

if user && user.authenticated?(cookies[:remember_token])

log_in user

@current_user = user

end

このifの条件の書き方はどういう意味だ

 

form_for(:session, url: login_path)
これの第二引数はいったいなんだ?僕のもってる本ではここにオブジェクトが入れられてたんだが。。。さらにリソースってなんだ?8.1.2

 

user && user.authenticate(params[:session][:password])

この部分がわからん。8.1.3

 

rubyでは変数に値が入ってたら booleanではtrueを返すから、userに値が入ってるかどうかを確かめるのが左辺。

右辺はauthenticateの部分がわからん。

 

ログインっていったいなんなんだ?ログイン時、たしかにクライアントに暗号を渡すことができたが、これを特定のユーザーと結びつける作業はいつやってるの?いまのままじゃあただ渡しただけのようにみえるのだが・・・userモデルに値を渡したわけでもない。わかめわかめわかめ

=>リスト8.4.5がすべて。これをつくるためにいままで頑張ってきた。

def authenticated?(remember_token)

return falseif remember_digest.nil?   

BCrypt::Password.new(remember_digest).is_password(remember_token) end

 このメソッドはログインしているかしてないかを確かめる機能をもつ。

このメソッドでサーバーに記憶されている remember_digest と クライアントに保存されている remember_token を比較している。authenticated?をログインしなきゃみれないページにペタペタ張っていけばいい。

 

 

 ログインってなんぞや?

ログイン状態 (ログインしているかどうか) は、一時セッションのユーザーIDか、永続的セッションの一意な記憶トークンに基いた現在のユーザーが存在しているかどうかで決定されます

 これが、スッキリ理解できなきゃだめなんだろな。。。いまはぼんやりしかわからず、どのコードでこれを実行したのかわからん。

 

 

 

 

 

 

 

インスタンスメソッドとクラスメソッドの違いが判らん

この新しいdigestメソッドではユーザーオブジェクトが不要なので、このメソッドもUserモデルのクラスメソッドとして作成することにします

とかいてあるが。リスト8.31の上。また、これらは必ずモデルファイルに書かれるが、意味があるのか?たしかにrailsでつかってるクラスはモデルクラスを表すが関係あるのか?

 

 

def remember

self.remember_token = User.new_token update_attribute(:remember_digest, User.digest(remember_token))

end

リスト8.32

 これでupdate_attributeの中のremember_tokenはself. が抜けてるがそんなつかいかたしてもいいの?

→いいらしい。でも2行目みたいに値を代入するときはつけなきゃならん。『たのしいRuby』という本をもっている人はp137をみたらいい。まったく同じことを書いている。セッター、ゲッターという言葉を知ってるひとにはこう説明したらいいかな。セッターはselfをつけるが、ゲッターはつけなくてもいい。

attr_accessor :remember_token この操作はそもそもセッターゲッターをつくるものだったことを思い出せ。知らん人は基礎からやり直せ。Rubyの話であって、railsの話ではない。

 

 

モデル、コントローラー、ヘルパーのあちこちでメソッドを定義しているが、コントローラーで定義するか、モデルで定義するかの違いってなんかあるの?

 

 

2周目

1840-2005

気づいたらはじめから8.3まえを読み終えた。遅いのか、早いのかさっぱりわからん。まあなんにせよ一週目よりかは理解ができたことには間違いない。

この章で著者が

本章では、アプリケーション全体で共通するログインシステムの細かい部分を多数扱うので、その分他の章に比べて長く、難易度も高くなっています。細部にとらわれると苦しくなるばかりなので、この章を完了するためにも、完璧に理解しようとするよりも、とにかく辛抱強く節をひとつずつ終わらせることを優先してください。

なお、多くの読者が「この章を2回通して完了すると学習効果が非常に高まった」との報告を寄せてくれています。皆さんも、可能であればこの章を2回通して行うことをおすすめいたします。

 とか書いてたがほんとだった。ムズイので一回目は死んだような目で眺めるだけでもいい。2回目になったらもっと理解できてるはず。でもただ眺めるだけでなく、わからない場所と気になったりぎりぎり理解できた箇所や調べた箇所はどこかに書き留めておいたほうが吉。

疲れたのでコンビニでポテチを買ってくる。塩味。うまし。

 

2212~2220

寝れないのでプログラミング開始する。とおもったらすぐ眠たくなった。寝る。

 

16/11/28

 

0631~0745 はじめ~8.4.6

20分くらいニュースみてた。大阪万博の話がでてた。

もういちど始めから見た。より理解できた。

 

0803ー0833 8.4.6~最後

にちゃん見てきたけど秋田県。大学食堂が50円で食べられるのでつぎ集中切れたらいこう。おなかすいたったったったった。

 まあまあ一回目よりかは理解できた。そういえば機能のことだったのか。すっかり昔のことに思える。一ヶ月は短いが、昨日のことは遠くのように思えてくる。なんなんだこの感覚は。まあいいや。10章に戻ります。さよならさよなら。