Authlogic

認証ライブラリRubyRailsActiveRecordセッション管理暗号化セキュリティ

認証ライブラリ

Authlogic

概要

AuthlogicはRuby on Rails用のシンプルで柔軟な認証ライブラリです。ActiveRecordベースで、従来のMVCパターンに従った非侵入的な設計が特徴です。DeviseやClearanceのような重厚なソリューションとは異なり、最小限の機能を提供し開発者に高度なカスタマイズ性を提供します。2025年現在も活発に開発が続けられ、最新版6.5.0がリリースされています。

詳細

AuthlogicはRuby on Railsアプリケーションに認証機能を追加するためのActiveRecordベースのライブラリです。以下の主な特徴があります:

  • ActiveRecord統合: acts_as_authenticメソッドでUserモデルに認証機能を追加
  • セッション管理: Authlogic::Session::Baseを継承したセッションモデル
  • 暗号化: BCryptなど設定可能な暗号化プロバイダーによるパスワードハッシュ化
  • バリデーション: メールアドレス、パスワード強度の自動バリデーション
  • カスタマイズ性: 認証ロジックやバリデーションルールの柔軟な変更
  • 非侵入的設計: 既存のモデルとコントローラーの構造を変更しない

メリット・デメリット

メリット

  • シンプルで理解しやすい設計により学習コストが低い
  • 高度なカスタマイズが可能で独自の認証ロジックを実装しやすい
  • ActiveRecordパターンに従った直感的なAPI
  • 軽量でアプリケーションのパフォーマンスへの影響が少ない
  • 長期間にわたって安定した開発とメンテナンス
  • 既存のRailsアプリケーションへの統合が容易

デメリット

  • 最新の認証機能(OAuth、2FA等)は手動実装が必要
  • Deviseと比較して標準機能が少ない
  • 初期設定とセットアップが他のgemより多い
  • コミュニティとエコシステムがDeviseより小さい
  • モダンなフロントエンド(SPA)との統合に追加作業が必要

参考ページ

書き方の例

Gemfileへの追加とインストール

# Gemfile
gem 'authlogic', '~> 6.5'

# インストール
bundle install

Userモデルの設定

# app/models/user.rb
class User < ApplicationRecord
  acts_as_authentic do |config|
    config.email_field = :email
    config.require_password_confirmation = false
    config.validate_login_field = true
    config.validate_email_field = true
    config.validate_password_field = true
    config.merge_validates_length_of_email_field_options minimum: 1
    config.merge_validates_format_of_email_field_options with: /@/
    config.crypto_provider = Authlogic::CryptoProviders::BCrypt
  end
  
  # バリデーション(オプション)
  validates :login, presence: true, uniqueness: true, length: { minimum: 3 }
  validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP }
end

UserSessionモデルの作成

# app/models/user_session.rb
class UserSession < Authlogic::Session::Base
  # セッション設定のカスタマイズ
  find_by_login_method :find_by_login_or_email
  remember_me_for 2.weeks
  
  # フックメソッド(オプション)
  def to_key
    new_record? ? nil : [send(self.class.primary_key)]
  end
  
  def persisted?
    false
  end
end

コントローラーでの認証処理

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  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&.user
  end
  
  def require_user
    unless current_user
      store_location
      flash[:notice] = "You must be logged in to access this page"
      redirect_to new_user_session_url
      return false
    end
  end
  
  def require_no_user
    if current_user
      store_location
      flash[:notice] = "You must be logged out to access this page"
      redirect_to account_url
      return false
    end
  end
  
  def store_location
    session[:return_to] = request.url
  end
  
  def redirect_back_or_default(default)
    redirect_to(session[:return_to] || default)
    session[:return_to] = nil
  end
end

ログイン処理(UserSessionsController)

# app/controllers/user_sessions_controller.rb
class UserSessionsController < ApplicationController
  before_action :require_no_user, only: [:new, :create]
  before_action :require_user, only: :destroy
  
  def new
    @user_session = UserSession.new
  end
  
  def create
    @user_session = UserSession.new(user_session_params)
    if @user_session.save
      flash[:notice] = "Login successful!"
      redirect_back_or_default account_url
    else
      render :new
    end
  end
  
  def destroy
    current_user_session.destroy
    flash[:notice] = "Logout successful!"
    redirect_back_or_default new_user_session_url
  end
  
  private
  
  def user_session_params
    params.require(:user_session).permit(:login, :password, :remember_me)
  end
end

ユーザー登録処理(UsersController)

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :require_no_user, only: [:new, :create]
  before_action :require_user, only: [:show, :edit, :update]
  
  def new
    @user = User.new
  end
  
  def create
    @user = User.new(user_params)
    
    if @user.save
      flash[:notice] = "Account registered!"
      redirect_back_or_default account_url
    else
      render :new
    end
  end
  
  def show
    @user = current_user
  end
  
  def edit
    @user = current_user
  end
  
  def update
    @user = current_user
    
    if @user.update(user_params)
      flash[:notice] = "Account updated!"
      redirect_to account_url
    else
      render :edit
    end
  end
  
  private
  
  def user_params
    params.require(:user).permit(:login, :email, :password, :password_confirmation)
  end
end

マイグレーション例

# db/migrate/create_users.rb
class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string :login,               null: false
      t.string :email,               null: false
      t.string :crypted_password,    null: false
      t.string :password_salt,       null: false
      t.string :persistence_token,   null: false
      t.string :single_access_token, null: false
      t.string :perishable_token,    null: false
      
      # Magic columns, just like ActiveRecord's created_at and updated_at
      t.integer :login_count,        null: false, default: 0
      t.integer :failed_login_count, null: false, default: 0
      t.datetime :last_request_at
      t.datetime :current_login_at
      t.datetime :last_login_at
      t.string :current_login_ip
      t.string :last_login_ip
      
      t.timestamps null: false
    end
    
    add_index :users, :login
    add_index :users, :email
    add_index :users, :persistence_token
    add_index :users, :single_access_token
    add_index :users, :perishable_token
  end
end