moxt

Just another Blog site

意識低いRuby on Rails再入門4

      2015/07/03

下記の内容を読んでテスト系の処理をすっ飛ばしたメモ。
http://railstutorial.jp/chapters/sign-in-sign-out?version=4.0#top

Userモデルを作ってログインしたりセッション管理したい。

Userモデルを作る

rails generateコマンドで作る
キーはname,email,password_digestにする。

マイグレーションファイルが生成されるので、マイグレーションする

Userモデルができた。

Userモデルにhas_secure_passwordという文を宣言すると、パスワードを平文ではなくハッシュ化された状態で管理することができる。らしい。

https://github.com/rails/rails/blob/869a90512f36b04914d73cbf58317d953caea7c5/activemodel/lib/active_model/secure_password.rb

何ができるモノなのか全く掴めないのでコードに書いてる説明を読んでみる。

This mechanism requires you to have a +password_digest+ attribute.

password_digestというキーを追加していた理由はこれだ。

Add bcrypt (~> 3.1.7) to Gemfile to use #has_secure_password:
gem ‘bcrypt’, ‘~> 3.1.7

bcryptというgemが必要らしい。
このgemを利用してpassword_digestを暗号化して保存してくれてるみたい。

Gemfileを見るとbcryptがコメントアウトされてるので、外してbundle installする。

インストールできたら実際にUserを作ってみる。(サンドボックスモードで)

まず、パスワード無しでユーザを作ってみる。

しっかりロールバックされている。

次にパスワードを入力してユーザを作ってみる。

作られたっぽい。

Userの新規登録画面を作るなり、コンソールから作るなりして自分用のUserを作る。

自分のアカウントでログインしたい

ログインとは何か

普段、我々は当たり前のように何かのウェブサービスにログインしていると思う。
ログインしているとは何なのだろうか。

ログインしていないと、いいねもできなければ、自分のプロフィールを編集したりすることもできない。

私は日本太郎です。と、各ページを閲覧するため、いいねするため、プロフィールを編集するためにサーバにたいして表明しなければいけない。

ブラウザ上でイケてるhtmlを見るためにhttp、httpsという通信ルールを使ってデータをやりとりしている。

で、このhttp,httpsっていうのは状態を持たない。
『前の通信してきた人が日本太郎さんだったから、この通信も日本太郎さんだね。じゃあ、プロフィール編集していいよ。』と文脈を読んでくれない。

じゃあ、どうすれば良いのか。

『毎回ログインさせる』という方法がある。

ページの遷移をするたび、いいねボタンを押すたび、プロフィール編集画面で『登録』ボタンを押すたびにログインさせるのだ。
そうすれば、日本太郎さんがいいねボタンを押した、プロフィール編集ページに遷移した、ということが保証できるはず。

しかし、面倒すぎる。

セッションの出番だ

なので、セッションという方法を使う。
通行手形のようなモノだ。
これをサーバへのリクエストに付加して通信を行う。
サーバはセッションを受け取り、それが有効であるか確認する。
有効であればリクエスト本来の処理を実行してレスポンスを返す。
無効なセッションであればエラーを表示するなり、ログイン画面に飛ばしたりする。

セッションの受け渡し方はいろいろある、リクエストのパラメータに含める、ヘッダーに追加する、Cookieに追加する、などなど。

Cookieで。

アカウントにセッションを持たせるようにする

セッションを受けたはいいが、そのセッションからUserを取得するにはどうすればいいのだろう。
Userにセッション用のカラムを追加する方法はどうだろう。

既存のテーブルにカラムを追加する場合もModelを作成したときに使ったmigrationファイルが活躍する。

新たにremember_tokenというカラムを追加してみる。

上のように

AddColumnToXXX 追加したいカラム名:型

と、書くと

このようにカラムを追加する文を勝手に追加したマイグレーションファイルが生成される。
railsの強力さを垣間見る。

マイグレーションファイルができたらマイグレーションしよう。

これでUserクラスにセッションの文字列を保持する新たなメンバーが追加された。
次にセッション管理用(ログイン・ログアウト)のControllerを作る。

セッション管理用の画面を作る

新しくControllerを作る必要があるので、rails g controllerを使う。

bundle exec rails g controller Sessions

Controllerができた。
ログインページを作る。
エンドポイントはnewが良さそう。

routes.rbにエンドポイントを明記しておくことも忘れないように。

resourcesというrailsが用意してるメソッドを使うとRESTfulなエンドポイントたちを自動で作ってくれる。
http://railsdoc.com/references/resources

onlyオプションをつけて不要なエンドポイントは作らないようにする。

Controllerにnewメソッドを追加したら、次のようなViewファイルをviews/sessions以下につくる

sessions/newにアクセスするとそれらしい画面が表示される。

ログインボタンを押すと、エラーが表示される。
Controllerにcreateがないからだ。
なのでcreateを追加する。

createではリクエストのパラメータからUserクラスを取得、その可否でログインの成功失敗を判断して適当なViewをレンダリングする。

与えられたパラメータからUserを取得できたら、remember_tokenとクライアントに返すCookieにセッション情報を格納する必要がある。

さて、肝心のセッション情報は誰が、どうやって作成するべきだろうか。
Userクラスに任せよう。

どうやって作るか、を考える前にセッション情報の性質とはどんなものか考える。

まず、セッション情報は重複してはいけない。

重複するということは1つのセッションに複数人のアカウントが紐付いている状態だ。
例として、プロフィール編集画面でセッションが必要な場合を考える。
セッションに対して複数人のアカウントが紐付いていると、誰のプロフィール情報を表示すればよいかシステム側で判断できない。これは困る。

なので、セッション情報は重複してはいけない。

フルスタック(笑)なRailsには便利な機能があって下記を呼ぶだけでbase64エンコードされたランダムな文字列が生成される。
SecureRandom.urlsafe_base64

Userのクラスメソッドでremember_token用の値を生成できるようにする。
インスタンスメソッドにすると、いちいちUserクラスをnewして生成してからメソッドを呼び出さないといけない。
また、new_remember_tokenメソッドは各Userインスタンスごとのメンバー変数に依存した処理ではない。
なので、クラスメソッドにする。

このメソッドをつかってログイン用の処理をControllerに書いてゆく。(本当はこういう処理をControllerに書いたら良くないんだけど。。w)

もう一度ログイン画面を開き、必要な情報を入力してログインしてみる。
ブラウザのデベロッパーツールなどでCookieを見てみると、remember_tokenというキーに謎の文字列が格納されていることが確認できるかと思う。

rails consoleで該当するUserの情報を見てみると、remember_tokenに謎の文字列が格納されている。

これでログイン処理ができたので、リクエストごとにセッションをつけて遷移できるようになった。
また「いいね」などのアクションを行う際にも、このセッションを見てユーザを一意に特定することができるためアクションごとにログインさせる必要もない。

ついでにログアウト機能も作る。

ログアウト=セッションを無効化する、と考えてよい。

SessionControllerにdestroyを追加し、ログアウト用の処理を追加する。(本当はこういう処理をControllerに書いたら良くないんだけど。。w)

このログアウト機能を呼ぶためのViewが必要になる。
ウェブアプリの中で常に表示させておきたいのか、特定の画面だけでログアウトできるようになってればいいのか、要件次第だと思う。
この辺は長くなりそうなので別に書く。

次はHelperクラスを利用してControllerに書かれていたログイン用の処理を切り出してControllerを見通しよくしてみたい。

 - プログラミング

336px




336px




  • このエントリーをはてなブックマークに追加
  • follow us in feedly

  関連記事