2009年11月21日土曜日

Authlogic バージョン2.1.3 (README.rdoc)

今回はAuthlogicというRuby製の認証用ライブラリのREDME文書(バージョン2.1.3時点)を訳してみました。先日、Deviseについての記事私訳)を読んだのですが、その記事の中で比較として挙げられていたライブラリでした。Deviseも良さそうですが、実際に記事の言っていることが正しいのかを判断しようと思い、Authlogic自体を理解するためにREADMEを文書を読んで、ついでとして、訳してみることにしました。

仕事で認証な必要なウェブアプリケーションを書いたことがあるのですが、Authlogicでできることと重複するようなことをやってることに気づきました。うーん、DRY。機会があれば、AuthlogicやDeviseなどを使って、書き直すことができればなぁ…



Authlogic

Authlogicは、簡潔で柔軟なRubyで記述された認証ソリューションです。

コードで例示して説明した方がいいでしょう…

Authlogicでは新しい型のモデルを提供しています。他のモデルのようにいくつでもどんな名前で必要なだけ作成することができます。この例では、クラス名から分かるようにUserモデルを使って認証を行おうとしています。

class UserSession < Authlogic::Session::Base
    # ここでは以下のように設定項目を記述します:
    # logout_on_timeout true
    # ...その他の設定項目については文書を参照して下さい
  end
ログイン時には以下のいずれかの例を利用します。UserSessionControllerのインスタンスを作成して、他のモデルのように使用します。
UserSession.create(:login => "bjohnson", :password => "my password", :remember_me => true)
  session = UserSession.new(:login => "bjohnson", :password => "my password", :remember_me => true); session.save
  UserSession.create(:openid_identifier => "identifier", :remember_me => true) # authlogic-oidという「アドオン」gemパッケージが必要
  UserSession.create(my_user_object, true) # 認証を回避してユーザーとして直接ログイン、第2引数のtrueは認証を記憶しておくという意味
上記の例では認証処理の全てを処理します。最初に認証をして、それから、適切なセッションの値やセッションを維持するためのクッキーを設定します。自作の認証ソリューションを使うときと同じように処理を行います。 次のようにログアウト、もしくは、セッションを破棄することもできます:
session.destroy
セッションが作成されてから、リクエスト間でそれを維持することができます。次のようにユーザーをログインした状態にします:
session = UserSession.find
作成したモデルで便利な認証機能を利用したい場合は次のようにします:
class User < ActiveRecord::Base
    acts_as_authentic do |c|
      c.my_config_option = my_value
    end # 設定ブロックは任意
  end
こうして妥当性確認などを処理することができます。認証時にloginという列があればそれを使い、なければ、emailという列を使うというある意味「賢い」機能もあります。このような動作は全て設定可能ですが、ほとんどの場合において上記のような動作が必要となるだけでしょう。 また、セッションは自動的に管理されます。設定で管理を自動的に行うかどうかを切り替えることができますが、次の例では、登録が成功した後に自動的にユーザーをログインさせます:
User.create(params[:user])
ユーザーがパスワードを変更した場合にもセッションを更新します。 Authlogicはとても柔軟で強力な公開APIがあり、動作の変更や拡張をするためのとても多くのフックがあります。詳細については以下のリンクを参照して下さい。

役立つリンク

直接、連絡を取る前に読んで下さい: もし、不具合や問題を発見した場合には、(GitHubの)問題セクションにポストして下さい。何か助けが必要な場合には、Googleグループで聞いて下さい。どちらも定期的にチェックしてますし、何かが起こればメールを受け取っています。そのため、助けが欲しい場合の一番いい場所です。将来、同じ質問や問題がある場合、他の人の参考になります。ご協力ありがとうございます。

Authlogicの「アドオン」

アドオンを作成した場合、このリストに追加しますので教えて下さい。または、プロジェクトをフォークしてリンクを追加して、プルリクエストを送って下さい。

セッションのバグ(ログインやログアウトに問題がある場合には読んで下さい)

明らかにApache/Passenger バージョン2.1.Xには、セッションが正しく動作しないという不具合があります。ログインやログアウトの時に起こる問題がある場合には、大抵、この問題が原因です。これはAuthlogicの問題ではありません。Passengerをアップデートするかセッションの保存方法をActiveRecordでの保存などに変更することでこの問題を解決することができます。

文書について

文書中にあるはずです。基本設計について理解するだけで十分です。 認証中に2つもモデルが関わっています。AuthlogicのモデルとActiveRecordのモデルです:
  1. Authlogic::Session,
    Authlogic::Session::Baseを拡張したセッションのモデル。

  2. Authlogic::ActsAsAuthentic,
    acts_as_authenticを呼び出してActiveRecordモデルに追加された機能。

上記のそれぞれのクラスには、一般的なロジックを実装しているいろいろなサブモジュールを含んでいます。サブモジュールは、設定、クラスメソッド、インスタンスメソッドなど全てに関与しています。 例えば、一定時間の活動しないユーザーをタイムアウトさせたい場合には、文書を参照して下さい。

Authlogic::ActsAsAuthenticサブモジュール

これらのモジュールは、ActiveRecord用で、acts_as_authenticメソッドを呼んで利用することができます。
  • Authlogic::ActsAsAuthentic::Base - Provides the
    acts_as_authenticというクラスメソッドを提供して、全てのサブモジュールを含んでいます。

  • Authlogic::ActsAsAuthentic::Email -
    emailの列に関しての全てを処理します。

  • Authlogic::ActsAsAuthentic::LoggedInStatus -
    便利な名前付きスコープとユーザーがログインしているかどうかを判定するメソッドを提供します。

  • Authlogic::ActsAsAuthentic::Login -
    loginの列に関しての全てを処理します。

  • Authlogic::ActsAsAuthentic::MagicColumns -
    login_count、failed_login_count、last_request_atなどの「特別な」列に関しての全てを処理します。

  • Authlogic::ActsAsAuthentic::Password -
    重要なモジュールで、パスワードを暗号化やsalt値を生成の生成を扱います。また、遷移パスワードアルゴリズムもサポートしています。

  • Authlogic::ActsAsAuthentic::PerishableToken -
    一時的なトークンの管理を扱います。また、トークンを使っているレコードを検索するためのクラスメソッドも提供します。

  • Authlogic::ActsAsAuthentic::PersistenceToken -
    永続的なトークンの管理を扱います。このトークンはユーザーのセッションを永続するためクッキーとセッション内に保存されます。

  • Authlogic::ActsAsAuthentic::RestfulAuthentication -
    restful_authenticationプラグインからの移行を簡単にするための設定オプションを提供します。

  • Authlogic::ActsAsAuthentic::SessionMaintenance -
    自動的なセッション管理を扱います。例えば、新規ユーザーの登録して自動的にログインさせたり、ユーザーがパスワードを変更して、セッションを更新するなどです。

  • Authlogic::ActsAsAuthentic::SingleAccessToken -
    ワンタイムアクセスのためのトークンの管理します。

  • Authlogic::ActsAsAuthentic::ValidationsScope -
    validates_uniqueness_ofの:scopeオプションのように全ての妥当性検査などにスコープを付けることができます。

Authlogic::Sessionサブモジュール

これらのモジュールはAuthlogic::Session::Baseを拡張したモデル用です。
  • Authlogic::Session::BruteForceProtection -
    ある一定の回数続けてログインに失敗したアカウントを無効にします。

  • Authlogic::Session::Callbacks -
    Authlogicを拡張したり、変更したり、追加したりするためのツールです。大抵の事柄にフックして実行することができます。Authlogicのプラグインやアドオンを開発したい場合はここから始めて下さい。

  • Authlogic::Session::Cookies - クッキーでの認証。

  • Authlogic::Session::Existence -
    オブジェクトの作成、保存、そして破棄。

  • Authlogic::Session::HttpAuth - HTTPのBasic認証による認証。

  • Authlogic::Session::Id -
    IDによるセッションを有効にする。これによって、1人のユーザーが複数のセッションを使用できる。

  • Authlogic::Session::MagicColumns -
    ActiveRecordでのcreated_atやupdated_at列のようなデータベースでの「特別な」列を管理。

  • Authlogic::Session::MagicStates -
    active?、approved?、そして、confirmed?といったレコードの状態を元にした自動的な妥当性確認。これは対応するレコードが存在する場合のみ。

  • Authlogic::Session::Params -
    ワンタイムアクセストークンのようなパラメータでの認証。

  • Authlogic::Session::Password -
    伝統的なユーザー名とパスワードでの認証

  • Authlogic::Session::Persistence -
    セッションの永続化やセッションの検索

  • Authlogic::Session::Session -
    セッションでの認証。セッションコントローラそのものです。

  • Authlogic::Session::Timeout -
    ある一定時間活動がない場合、自動的にログアウト。

  • Authlogic::Session::UnauthorizedRecord -
    ActiveRecordのオブジェクトを直接渡すことでの認証の取り扱い。

  • Authlogic::Session::Validation -
    妥当性確認やエラー確認。

その他のモジュール

認証プロセスを通じて共有されるその他のモジュールや「ユーティリティ」モジュールやクラス。
  • Authlogic::AuthenticatesMany -
    親のレコードへセッションにスコープを付けることができるようにする。has_manyやbelongs_toでの関係のようにセッションにも同じようなことができます。

  • Authlogic::CryptoProviders -
    Authlogicで利用する様々な暗号化アルゴリズムを含んでおり、どのアルゴリズムを使うかを選択することができます。

  • Authlogic::I18n -
    RailsのI18nライブラリと同じように動作して、Authlogicに国際化の機能を提供します。

  • Authlogic::Random -
    ランダムなトークンを生成するための単純なクラスです。

  • Authlogic::Regex -
    Authlogicでログや電子メールのフォーマットの妥当性を確認するための正規表現を含んでいます。

  • Authlogic::TestCase -
    作成したコードのテストを手助けするためのフレームワークをテストするための様々なヘルパーメソッド。

  • Authlogic::Version -
    数々の方法でAuthlogicのバージョンを確認するための便利なクラス。

Railsでの簡単な例

セッションの作成が表面上はORMライブラリのように動作するならどうなるでしょう…
UserSession.create(params[:user_session])
ユーザーセッションコントローラが他のコントローラのようであればどうなるでしょう…
class UserSessionsController < ApplicationController
    def new
      @user_session = UserSession.new
    end

    def create
      @user_session = UserSession.new(params[:user_session])
      if @user_session.save
        redirect_to account_url
      else
        render :action => :new
      end
    end

    def destroy
      current_user_session.destroy
      redirect_to new_user_session_url
    end
  end
ごらんの通り、RESTfulの開発パターンに見事に当てはまります。ビューはどうなるでしょう…
<% form_for @user_session do |f| %>
    <%= f.error_messages %>
    <%= f.label :login %><br />
    <%= f.text_field :login %><br />
    <br />
    <%= f.label :password %><br />
    <%= f.password_field :password %><br />
    <br />
    <%= f.submit "Login" %>
  <% end %>
また、セッションを永続化する場合には…
class ApplicationController
    helper_method :current_user_session, :current_user

    private
      def current_user_session
        return @current_user_session if defined?(@current_user_session)
        @current_user_session = UserSession.find
      end

      def current_user
        return @current_user if defined?(@current_user)
        @current_user = current_user_session && current_user_session.user
      end
  end

インストールと使い方

gem/プラグイン(推奨)でのインストール rubyforgeより:
$ sudo gem install authlogic
またはgithubから:
$ sudo gem install binarylogic-authlogic
それから、プロジェクトの設定にgemの依存性を追加するだけです。 または、プラグインとしてインストールできます:
script/plugin install git://github.com/binarylogic/authlogic.git

詳細な設定チュートリアル

詳細な設定チュートリアルについては、Authlogicを使ったサンプルを参照して下さい。このサンプルを作ったのはチュートリアルのためだけではなく、同じチュートリアルで使うサンプルアプリケーションのコードを試すことができるからです。問題がある場合、何が違うのかを比較することもできます。

テスト

Authlogicのもっとも良いことの一つはテストだと考えています。Authlogicは十分にテストが実施されているため、あなたのアプリケーションではたくさんの重複するテストを省略します。たくさんのテストはあなたのアプリケーションには含まれませんが、他のライブラリのようにAuthlogicはテストされた状態なのであなたのアプリケーションにはたくさんのテストが含まれません。 例えば、ActiveRecordについては、その内部のテストを実施しません。それは、ActiveRecordの作者たちが内部をテストしているからです。何百ものActiveRecordのテストをあなたのアプリケーションにコピーすることは意味をなしません。同じ事がAuthlogicにも言えるのです。他のアプリケーションのようにアプリケーション固有のコードをテストする必要があるだけです。 それはそれとして、Authlogic::TestCaseの項目をテストすることについてのあなたの疑問についての回答があるはずです。

Authlogicの動作について簡単な説明

Authlogic全体がどのように動作するのか興味がありますか?ActiveRecordのモデルについて考えてみて下さい。私用できるようになるには、データベースへの接続が確立されている必要があります。Authlogicの場合は、コントローラへの接続が確立されている必要があります。クッキー、使用中のセッション、HTTPのBASIC認証によるログイン情報などを変更するためにコントローラへの接続を利用します。現在のコントローラオブジェクトについてをAuthlogicへ知らせるために自動的にコントローラに設定される前処理を行うフィルターを利用してコントローラへ接続します。Authlogicはフィルターを利用して全てのことを行います。とても簡単か設計です。なにも変なことをしていません。Authlogicは、コントローラオブジェクト内でフレームワークが提供するツールを利用しているだけです。

Authlogicの特徴、及び、開発動機

Authlogicを作成する際に影響されたのはその時の認証ソリューションの乱雑さであった。つまり、ロジックが適切に整理されておらず、正しいとは思わなかった。知っているかもしれませんが、MVCデザインパターンでの一般的な誤解は、"M"で表されるモデルがデータアクセスのロジックのためだけだということです。それは間違いです。モデルは、問題ドメインのロジックのための場所なのです。この誤解がRESTfulデザインパターンと今までの認証ソリューションがうまく動作しなかった理由です。Authlogicでは、セッション管理ロジックをドメイン自身(または、モデル)内に配置することで、この問題を解決しています。セッション管理をドメイン自身に移動することの利点としては:
  1. よりクリーンであること。Authlogicにはジェネレータがありません。Authlogicでは平易なRubyのクラスを提供しています。もっと重要なことにあなたのアプリケーション内のコードはあなたが書きたいように書いたコードで、素晴らしくてクリーンです。あなたのアプリケーションの一部であるべきコードであり、アプリケーション固有ですが、冗長な認証パターンではありません。

  2. 簡単に最新であり続けること。私の言いたいことを理解するために他の認証ソリューションへのコミットを見て下さい。それから、Authlogicのコミットで簡単に更新して最新のコードを使い始めることができます。

  3. ドメインレベルで全て結合していること。新規ユーザーの登録を例に取る場合、ユーザーをわざわざログインさせることは全く理由がありません。Authlogicはこれをコールバックで処理します。同じ事がユーザーがパスワードを変更するときにも言えます。Authlogicではあなたに代わってセッション管理を処理します。

  4. 重複するテストが無いこと。Authlogicはgeneratorを使わないので、テストにも1番目の利点が適用されます。Authlogicは、十分にテストされています。アプリケーションを開発する度にActiveRecordの内部を精査してテストをしませんよね?Authlogicに対しても同じ事をしますか?開発しているアプリケーションのテストはそれ固有のコードのためだけであるべきです。関係ない部分を取り除いて、テストコードを的を得た簡潔なものにしましょう。次々とアプリケーションに同じテストコードをコピーするのを止めましょう。

  5. フレームワークにとらわれないこと。Rackを見てみて下さい。

  6. 単一のセッションに縛られていないこと。Apple社のme.comについて考えてみて下さい。そこでは、支払い情報を変更する前にもう一度認証を行う必要があります。このために2つ目のセッションを作成するのはどうでしょうか?それははじめのセッションのように動作します。それから、支払い情報のコントローラが「超安全な」セッションを要求することができます。

  7. 簡単に拡張できること。ライブラリを利用する明らかな特徴の一つとして、APIがあるならそれを利用できることです。Authlogicには素晴らしい公開APIがあります。つまり、簡単に拡張できてコアライブラリでできないことを実現することができます。どういう意味かについては上記の「アドオン」一覧を見て下さい。

Copyright (c) 2009 Ben Johnson of Binary Logic, released under the MIT license

(終)

訳文に間違いや分かりにくい点があれば、コメントやメールで連絡を頂けると幸いです。

0 件のコメント: