ラベル 認証 の投稿を表示しています。 すべての投稿を表示
ラベル 認証 の投稿を表示しています。 すべての投稿を表示

2013年1月30日水曜日

Railsのdeviseを使ってみる ~自動生成された標準の画面を調べよう7~

とういわけで前回からの残り部分『deviseを自分ちのアプリで(さしあたり)使うにはどうするか』について書きます。

こういうときはどういう使い方をしたいかをとりあえずあげるのがいいのであげます。
以下のカンジ。

  • ログイン前にルートページにアクセスすると自動的にログインページにいく
  • ログイン前はユーザ登録ができる
  • ユーザ登録完了後は[ログインしたものとする, ログインページに行く]のどちらかがいい
  • ログアウトをするとログインページに行く
これだとすると以下の設定でなんとかなるはず。
  1. ルートページをログイン後の初期画面(ポータルとかトップメニューページ等)とする
  2. ルートページにアクセスした際に未ログインであればログイン画面に飛ばすことにする
  3. ログイン画面にログアウトリンクを配置する
1. に関してはroutes.rbの:root_to で設定すればいいので省略。
2. に関してはJavaで言うところのログインチェックフィルター的なもので実現すればいい。
で調べてみたところ、『コントローラの実行前フィルターに認証フィルターを追加すればよい』、らしい。
日本語で書くとわかりにくいが用は認証チェックを行いたい画面のコントローラに

before_filter :authenticate_user userはモデル名

とすればいいらしい。
#認証フィルターの中身やfilterの機構そのものは今度調べてみたい。


今回は試験的に portalというコントローラ&画面のセットを作成してみた&ウチの認証用のモデルがdevise_userであるので
class PortalController < ApplicationController
  before_filter :authenticate_devise_user!

  #portalの初期表示用アクション
  def index
  end
  
  #普通はコレ以外にもデータ操作などの色々なアクションがある
end
のようにした。

3. についてはググったらすぐ出てきた。
ログアウトリンクを表示する部分で。
<%= link_to 'ログアウト', destroy_devise_user_session_path, method: :delete  %>
とすればいい。(うちはモデル名がdevise_userなので↑のようなヘルパーメソッド名になっている)

なので、今回であればポータル画面に↑のリンクを追加すれば良い。

コレmethod名がdeleteになっているのがポイント。
確かにルーティングを見ると

となっているので、DELETEメソッドじゃないと受付無いようになっている。

ちなみに↑の用にリンクを作っても何故かGETメソッドで飛ばしてしまうという事象にそうぐう*1 した人もいたもよう。
#railsとかdeviseのバージョンが関係しているのかな、とか思った。
#リンク生成ならrailsのバージョンによる影響な気もするが。。。

以上でやりたかったことはできたのでまとめると。

【もともとのねらい】

  • deviseの自動生成された画面及び処理を(そこそこ)理解する
  • (あんまり手をかけず≒自動生成されたものを活かして)自分ちのアプリに組み込む


【具体的にどういう仕様にするか】

  • ログイン前にルートページにアクセスすると自動的にログインページにいく
  • ログイン前はユーザ登録ができる
  • ユーザ登録完了後は[ログインしたものとする, ログインページに行く]のどちらかがいい
  • ログアウトをするとログインページに行く

【上記仕様を実現するために何をすればいいか】

  • ルートページをログイン後の初期画面(ポータルとかトップメニューページ等)とする:configのroutes.rbで root :to => "portal#index" を記載する。(無論publicのindex.htmlは削除する)
  • ルートページにアクセスした際に未ログインであればログイン画面に飛ばすことにする:ログインチェックをかけたい画面のコントローラに before_filter :authenticate_devise_user! を追加する。(devise_userは認証用のモデル名なのでモデル名を変えたらそれに合わせる)
  • ログイン画面にログアウトリンクを配置する:認証後の画面に < %= link_to 'ログアウト', destroy_devise_user_session_path, method: :delete  >  を記載する

ということであったらしい。
というわけで長かったdeviseの話も今回で一段落とします。
次回deviseが登場するのは中級編でしょう。そこでは以下のようなことをやるつもりです。

  • ユーザ登録データ制約のカスタマイズ(パスワード文字数は256文字以上じゃないとダメ!とか)
  • 自動生成された画面をカスタマイズする(見栄えを替えるとか自作するとか)
  • 各アクション後の遷移先ページをカスタマイズする(ログアウト後はログイン画面じゃなくてyahooに飛ばしたいんだ! とか)
  • 他のdeviseの機能について(飛ばしたconfirmとか)

一旦以上。


1:『そうぐう』という単語を見るたびにドラえもんの『未知とのそうぐう機』を思い出してしまう。使うとUFOが飛んできて未知との遭遇が体験できるというとんでもない道具だった。

2013年1月29日火曜日

Railsのdeviseを使ってみる ~自動生成された標準の画面を調べよう6~

前回まででGETで取得できる画面はだいたい取得できたので、今回は以下をやります。

  1. 画面遷移の整理(つながりとか)
  2. 自分ちのアプリでどう使えばいいかの手順の整理
今回が終われば自分ちのアプリに組み込めるからいい区切りになるはず。

1. 画面遷移の整理

今まで得た情報を元にすると以下の流れになっている。
#ちっちゃくてすいません。






ルーティングパスとパス消化状況(↑の図で登場してるか)は下記。
HTTPメソッドカラムの冒頭番号は図の遷移の番号と対応。
HTTPメソッドurlルートパラメータ
①GET/devise_users/sign_in(.:format)devise/sessions#new
②POST/devise_users/sign_in(.:format)devise/sessions#create
DELETE/devise_users/sign_out(.:format)devise/sessions#destroy
⑥POST/devise_users/password(.:format)devise/passwords#create
⑤GET/devise_users/password/new(.:format)devise/passwords#new
⑦GET/devise_users/password/edit(.:format)devise/passwords#edit
⑧POST/devise_users/password(.:format)devise/passwords#update
GET/devise_users/cancel(.:format)devise/registrations#cancel
④POST/devise_users(.:format)devise/registrations#create
③GET/devise_users/sign_up(.:format)devise/registrations#new
⑨GET/devise_users/edit(.:format)devise/registrations#edit
⑩PUT/devise_users(.:format)devise/registrations#update
DELETE/devise_users(.:format)devise/registrations#destroy



残ってるのは

  • /devise_users/sign_out
  • /devise_users/cancel
  • /devise_users (DELETEメソッド発行する奴)
の3つだが、

  • sign_out ⇒ ログアウトでしょ
  • cancel ⇒ よくわからないから一旦パス
  • DELETEメソッド発行する奴 ⇒ ユーザアカウント削除でしょ

と思われるのであとはなんとかなりそう。

というわけで次回自分のアプリへの設定手順を整理してdeviseは一段落とする。
#今回で終わらなかった。。。

2013年1月28日月曜日

Railsのdeviseを使ってみる ~自動生成された標準の画面を調べよう5~

というわけで前回の続きで画面を表示させてみる。
残りは
  • 3. ユーザ登録キャンセル
  • 5. パスワード更新画面表示
の2つ。
#前回は間違えて3より先に4をやってしまっていたらしい。

というわけでログインしている状態で上記2つを表示させてみる。


3. ユーザ登録キャンセル

でやってみたところ、起点画面に遷移して
You are already signed in.
と表示されてしまった。
むむむ。整理すると。
  • ログインしていない状態➡ログイン画面(Sing_in)画面へ飛ばされる
  • ログインしている状態➡『おまえはもうじゅうぶんにろぐいんしている』
と言われる。
この挙動から見るにこの画面は、『ログインしていない状態でアクセスするのが正しい』、ように見える。
#エラーメッセージが出るのがログイン済の状態なので。
悩んでもしょうがないのでコードを読んでみることにする。
/devise_users/cancel のアクションは devise/registrations#cancel であり、そのソースは下記。
#うちはRubyMineで開発しているので Command + N のクラス名を検索したところ、 devise/RegistrationController が発見できたのでそれで見た。
#テキストエディタの人はgemのdeviseのフォルダ以下(あるのかどうかもわからんけど)でも探しにいくことになるのでは無いかと推測。
#例によって日本語コメントはコチラで付記。
  
  # GET /resource/cancel
  # Forces the session data which is usually expired after sign
  # in to be expired now. This is useful if the user wants to
  # cancel oauth signing in/up in the middle of the process,
  # removing all OAuth session data.
  # セッションデータ(普通はSign_in後に破棄される)を直ちに破棄します。
  # これはユーザがOAuthのSign_in,Sign_up の処理を中断するのにベンリです。
  def cancel
    # sessionからdevise… というキーのデータ全部消す
    expire_session_data_after_sign_in!
    #registrasion#new へリダイレクト
    redirect_to new_registration_path(resource_name)
  end

うーん、完全に推測だけど以下のカンジだろうか。
  1. 認証方式をOAuthにする
  2. この状態で認証しようとするとdeviseは入力された情報をsessionに溜め込む
  3. その後OAuth認証を行おうとする
  4. で、途中で辞めたくなった場合に中途半端にsessionにOAuthのデータが残るとセキュリティ的にいまいちなので消す
ともあれとりあえずこの画面を後回しにするべき(なんか深くはまりそう&これより先に普通に使う画面について勉強した方がいい)ということだけはわかった。

5. パスワード更新画面

これも『こんなのログイン後にアクセスしたらパスワード変更画面が出るあれだろ、ハハハ』とか思ってアクセスしたところ。

起点画面に遷移して
You are already signed in.
と表示されてしまった。
あべし。

やむなしと思いなしてpassword#editの中身をのぞいてみると。

  # GET /resource/password/edit?reset_password_token=abcdef
  def edit
    self.resource = resource_class.new
    resource.reset_password_token = params[:reset_password_token]
  end

とほぼノーヒント状態。

#ちなみに後でわかるがこれはノーヒントなどではなく、もうクリティカルな回答そのものが提示されていた。

で、さんざん悩んだあげくgoogl先生に聞いてみたところ
コチラのすばらしいブログhttp://blog.livedoor.jp/nizoraul/archives/3622073.html
が同じようなこと(deviseの解説)をなされていたので、読み進めていくと以下の記載が。

そのあとで、自分のメールのユーザー作って、パスワードを綺麗サッパリ忘れます。 
 そのあとで、「Forgot your password?」からメールアドレスを入力して「send me reset password instructions」をクリックすると... 

おおぅなにやら英文のメールが届きました。そのなかの 
Change my passwordというのがあり、クリックするとパスワード変更ページが開きます。URLを見ると?reset_password_token=****のパラメータが設定されてますねぇ。



あー、わかった、この画面って。

  1. パスワードを忘れた人がパスワードリセット申し込み画面でメールアドレスを入力してリセットを申し込む
  2. 入力したアドレスにリセット画面のリンクが届く
  3. 該当リンクの画面を開いてパスワードリセットを行う
ってやつだ。
となるとそのリンクは  devise_users/password/edit?reset_password_token=zzzz
の的なヤツと推測できる。
#さっきのpassword#editの冒頭に思いっきり GET /resource/password/edit?reset_password_token=abcdef って書いてあるじゃん…、というのがクリティカルな回答でした。

でそのtokenはメールに書いてあるんだろうけど、『そのリンクの正当性を確認するためにはサーバ側にもその値を持っていなければならない』、だろうから多分DBに持ってるはず。
➡ DBのdevise_usersテーブルをのぞいてみるとそのものズバリ reset_password_token というカラムがいる。
で、パスワードリセットを実行したレコードにだけreset_password_token の値がセットされている。

ここまでくればやることはただ一つ。
/devise_users/password/edit?reset_password_token={DBに保存してあるトークン}
にアクセス。
#{}内は置換する。

でたー!



やったー。
苦労したので感慨一入だー。

という訳で今回はココまで。
次回は今までわかったこと、とくに画面遷移を整理して、実際に使う場合のやり方を明らかにしよう。

2013年1月27日日曜日

Railsのdeviseを使ってみる ~自動生成された標準の画面を調べよう4~

というわけで前回の続きで自動生成された画面を見ていく。
今回はログインしていなかったので表示できなかった3画面にリベンジする。

4. ユーザ編集画面表示

ログインしていない状態でリクエストするとログイン画面(Sign in)に飛ばされたやつ。

今度はできるだろと思って、ブラウザで localhost:3000/devise_users/edit にアクセスするとなんとエラー画面(rails のよくあるエラー画面)に。

エラー内容を読むと。

  • Devise/registrations#edit でメソッドありませんエラー発生
  • edit.html.erb の9行目で起きた
  • reconfirmableなんてメソッドないよ
ということらしい。
具体的には
<% if resource.class.reconfirmable && resource.unconfirmed_email.present? %>
というコードで落ちてる。
多分resourceは編集対象(つまりログインしている人のユーザデータ)をさすと思うので、resourceのclass(これはチョットわからん)にreconfirmableなんてメソッドないよ、と言ってるのだと推測。
で、エラーメッセージでググってみると、
『Hi それはconfig/intializers/devise.rbで config.reconfirmable = true になっているからさ!』
『Hi それはテーブルに必要なカラムがないからさ!』
的なのがあったのでdevise.rbを見直してみると、config.reconfirmable = false になっていた。
ウーン、なんでだろうと思ってテーブルを作成したmigrationを見直してみると
## Confirmable
# t.string   :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string   :unconfirmed_email # Only if using reconfirmable

とこっちは封印がされている。
で、とりあえずこいつらをテーブルに追加してみる。

空マイグレーション作成
rails g migration AddConfirmableToDeviseUsers

で中身を以下の感じに。
class AddConfirmableToDeviseUsers < ActiveRecord::Migration
  def change
    add_column :devise_users, :confirmation_token, :string
    add_column :devise_users, :confirmed_at, :datetime
    add_column :devise_users, :confirmation_sent_at, :datetime
    add_column :devise_users, :unconfirmed_email, :string
  end
end

でやってみた(ユーザ新規登録➡ユーザ編集)のだがさっきと同じエラーになった。
で、さらにググってみると
『Hi confirmableを使うならconfig.reconfirmable=trueにしてviewを生成するのさ!』
的なメッセージがあったので、
『これひょっとして、config.reconfirmable=trueの状態でview生成して、その後にfalseに設定したんじゃね?』
と思い直して、以下を実施。

  • 一旦deviseのviewを削除
  • config.reconfirmable=false に設定(していることを確認)
  • rails generate devise:viewを実施

で、できたedit.html.erbを見てみると
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
と生成結果が変わっている。
これは期待できる。
➡というわけでやってみた(ユーザ新規登録➡ユーザ編集)


できた。
#左端の青はスクリーンショットとるときに映り込んだうちのmacの背景

ソースは以下のカンジ。

Edit Devise user



(leave blank if you don't want to change it)

(we need your current password to confirm your changes)

Cancel my account

Unhappy?
. Back

というわけで本日は以下のノウハウと以下の課題が。

  • deviseでconfimationを使わない場合は設定ファイルで『設定しない』をやってからviewを作ること
  • そもそもconfirmation機能とはなにかを明らかにすること

長くなったので本日はここまで。
次回は画面表示の続き。

2013年1月26日土曜日

Railsのdeviseを使ってみる ~自動生成された標準の画面を調べよう3~

前回は生成されたview, model, migrationの中身をチラ見した。
今回は実際にリクエストを打って画面を表示させてみよう。

この前のルーティング情報に基づくといきなり表示できそうなのは以下。
#ちなみにHTTPメソッドは全部GET
  • ログイン画面表示 /devise_users/sign_in
  • ユーザ登録画面表示 /devise_users/sign_up
  • ユーザ登録キャンセル /devise_users/cancel
  • ユーザ編集画面表示 /devise_users/edit
  • パスワード更新画面表示 /devise_users/password/edit
  • パスワード??? /devise_users/password/new

順番に画面を表示させてみよう。

1. ログイン画面
ブラウザで localhost:3000/devise_users/sign_in にアクセスすると以下の感じに。















で、表示されているソースを見ると以下のようになっていた。
#例によって日本語コメントはコチラで追記。

Sign in



Sign up Forgot your password?

サマリーすると。

  • ログイン用フォーム
  • ユーザ新規登録へのリンク
  • パスワード忘れた人用のリンク
の3つがこの画面のコンテンツということになる。

2. ユーザ登録(Sing_up)画面

ブラウザで localhost:3000/devise_users/sign_up にアクセスする or ログイン画面のSing upリンクをクリックすると以下の画面が出てくる。
















で、表示されているソースを見ると以下のカンジ。
#例によって日本語コメントはコチラで追記。

Sign up





Sign in Forgot your password?


で、見てみると /devise_users/password/new はパスワード忘れた人用リンクのURLとなっている。

つまり 
  • パスワード??? /devise_users/password/new
の正体は

  • パスワードを忘れた人へ /devise_users/password/new
と思われる。
3. ユーザ登録キャンセル

これはいきなり表示できない気がするけど、とりあえずやってみる。
ブラウザで localhost:3000/devise_users/cancel にアクセスするとさっきのユーザ登録画面(SignUp)が表示された。
まあ、うまく行かないとは思ってた。
一旦後回し。

4. ユーザ編集画面表示


これもログインしていない状態じゃ表示できない気がするけど、とりあえずやってみる。
ブラウザで localhost:3000/devise_users/edit にアクセスすると今度はログイン画面(SignUp)が表示された。
ユーザのデータ修正するならまずログインしなさい、ということでしょう。
一旦後回し。

5. パスワード更新画面表示

これも4.同じ結果なので省略。


6. パスワード???

ブラウザで localhost:3000/devise_users/new 以下のカンジになった。













うむ、ヤハリ正体はパスワードを忘れた人用画面だった。
ソースは以下のカンジ。

Forgot your password?


Sign in Sign up


といったあたりで今回はココまで。
次回はユーザを作ってみて今回表示できなかった画面を表示する予定。

2013年1月25日金曜日

Railsのdeviseを使ってみる ~自動生成された標準の画面を調べよう2~

前回の続きでviewとモデルについてみていくことにします。
#ただviewは枚数が多いので一旦どんなものがあるかぐらいで、止めます。

1. できたview
まずviewはこれだけあった。

結構あるようだ。
認識していたのは
  • sessions
  • registrations
  • passwords
の3つ。
それ以外は多分以下。
#予測の説明付記。
  • confirmations:何らかの確認を行うための画面。『このデータでユーザ登録しますか?』『パスワードを初期化していいですか?』的な。
  • mailer:メールを送信する画面。パスワードリセットとかだろうか?
  • shared:コレはちょっと分からん。
  • unlocks:コレはロックされたアカウントの解放だと思われる。

2. できたモデル
#日本語コメントはコッチで付記。

class DeviseUser < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  # (このクラスは)デフォルトのデバイスモジュールを含んでいます。
  # コレ以外にも
  # :token_authenticable トークン認証可否
  # :confirmable 確認可否
  # :lockable アカウントロック可否
  # :timeoutable タイムアウト制御可否
  # :omniauthable OmniAuth可否
  # があります。

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  # このモデルでのアクセサ(Javaでいうとgetter,setter)を定義します
  attr_accessible :email, :password, :password_confirmation, :remember_me
  # attr_accessible :title, :body
  # title, body属性へのアクセサはコメントアウトしています。
end

deviseメソッド(devise :database_authenticable, … の部分)がこのモデルのポイントになると思うので今度のぞいてみよう。

3. できたマイグレーション

最後にテーブル作成マイグレーション(コレ長い)
#コチラも日本語コメントはコチラで付記。

class DeviseCreateDeviseUsers < ActiveRecord::Migration
  def change
    create_table(:devise_users) do |t|
      ## Database authenticatable
      # データベース認証用カラム(メールアドレス, 暗号化パスワード)
      t.string :email,              :null => false, :default => ""
      t.string :encrypted_password, :null => false, :default => ""

      ## Recoverable
      # アカウント復旧用カラム(パスワードリセット用トークン, リセットパスワード送信先
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      # 思い出し用(よくわからん)カラム
      t.datetime :remember_created_at

      ## Trackable
      # アカウント履歴用カラム(ログイン回数, 現行ログイン時刻, 最終ログイン時刻, 現行ログインIP, 最終ログインIP)
      t.integer  :sign_in_count, :default => 0
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      # 確認用カラム(デフォルト封印)
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # ロック用カラム(デフォルト封印)
      # t.integer  :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      ## Token authenticatable
      # トークン認証用カラム(デフォルト封印)
      # t.string :authentication_token

      t.timestamps
    end
    
    # インデックス作成
    add_index :devise_users, :email,                :unique => true
    add_index :devise_users, :reset_password_token, :unique => true
    # add_index :devise_users, :confirmation_token,   :unique => true
    # add_index :devise_users, :unlock_token,         :unique => true
    # add_index :devise_users, :authentication_token, :unique => true
  end
end

といったところで今回はここまで。

次回はリクエストでも打って表示された画面を見てみたい。