Ruby初心者必見!5ステップで完璧なログイン機能を作成する方法

Rubyでログイン機能を作るステップRuby
この記事は約16分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Rubyを使用したログイン機能の作成は、Web開発の基本的なスキルとも言えます。

この記事では、Ruby初心者でも簡単にログイン機能を作る方法を、具体的なサンプルコードと詳細な解説とともに5つのステップでご紹介します。

ログイン機能の実装は一見複雑に見えますが、順序立てて一つずつ手順を踏んでいけば、誰でも成功させることができます。

●Rubyの基本

ログイン機能を作る前に、まずRubyの基本的な知識を理解することが必要です。

具体的には、データ型と制御構造、そしてオブジェクト指向とクラスについて学ぶことになります。

○データ型と制御構造

Rubyでは、数値や文字列、配列などさまざまなデータ型を扱うことができます。

これらのデータ型は、ログイン機能の作成において必須の知識です。また、制御構造についても理解することが重要です。

制御構造はプログラムの流れをコントロールするための機能で、例えば条件分岐(if文)やループ(while文、for文)などがあります。

○オブジェクト指向とクラス

Rubyはオブジェクト指向言語です。

オブジェクト指向とは、実世界の事象をオブジェクトとして表現し、そのオブジェクト間のやりとりによってプログラムを進める設計思想のことを指します。

このオブジェクト指向を理解するためには、クラスの概念を理解することが必要です。

クラスはオブジェクトの設計図で、同じ特性や振る舞いをもつオブジェクトを生成するために使用します。

●ログイン機能の作り方

ここからは、Rubyでログイン機能を作るためのステップを具体的に解説します。

○ステップ1:ユーザーモデルの作成

まずはユーザー情報を管理するためのモデルを作成します。

モデルはデータベースとのやり取りを担当する部分です。

□サンプルコード1:ユーザーモデルの作成

class User
  attr_accessor :username, :password

  def initialize(username, password)
    @username = username
    @password = password
  end
end

このコードではUserというクラスを作成し、ユーザーネームとパスワードを属性として持つオブジェクトを生成するための設計図を作っています。

この例ではattr_accessorメソッドを用いてユーザーネームとパスワードに読み書きのアクセスを許可し、initializeメソッドを用いて新たなUserオブジェクトが作成される際にユーザーネームとパスワードを初期設定しています。

このコードを実行した場合、次のように新たなUserオブジェクトを生成できます。

user = User.new("username", "password")

このコードを実行すると、usernameとpasswordが初期設定された新たなUserオブジェクトが生成されます。

○ステップ2:ログインフォームの作成

ログイン機能を作成するためには、ユーザーが自分の情報を入力するためのインターフェースが必要です。

このため、次にログインフォームを作成します。ログインフォームはユーザーのユーザーネームとパスワードを受け取る部分です。

□サンプルコード2:ログインフォームの作成

class LoginForm
  attr_accessor :username, :password

  def initialize(username, password)
    @username = username
    @password = password
  end
end

このコードではLoginFormというクラスを作成し、ユーザーネームとパスワードを属性として持つオブジェクトを生成するための設計図を作っています。

この例ではattr_accessorメソッドを用いてユーザーネームとパスワードに読み書きのアクセスを許可し、initializeメソッドを用いて新たなLoginFormオブジェクトが作成される際にユーザーネームとパスワードを初期設定しています。

このコードを実行した場合、次のように新たなLoginFormオブジェクトを生成できます。

form = LoginForm.new("username", "password")

このコードを実行すると、usernameとpasswordが初期設定された新たなLoginFormオブジェクトが生成されます。

このLoginFormオブジェクトは、ユーザーがログインフォームに入力した情報を受け取り、それを次のステップであるセッションの作成に使用します。

○ステップ3:セッションの作成

ユーザーがログイン情報をフォームに入力した後、その情報はどこかに保存される必要があります。ここで登場するのがセッションです。

セッションはサーバー側で管理される、一時的な情報の格納場所です。

セッションを使うことで、ユーザーがログインした状態を保持することができます。

□サンプルコード3:セッションの作成

class Session
  attr_accessor :user

  def initialize(user)
    @user = user
  end
end

このコードではSessionというクラスを作成し、ログインしたユーザー情報を属性として持つオブジェクトを生成するための設計図を作っています。

この例ではattr_accessorメソッドを用いてuserに読み書きのアクセスを許可し、initializeメソッドを用いて新たなSessionオブジェクトが作成される際にuserを初期設定しています。

このコードを実行した場合、次のように新たなSessionオブジェクトを生成できます。

user = User.new("username", "password")
session = Session.new(user)

このコードを実行すると、userが初期設定された新たなSessionオブジェクトが生成されます。

このSessionオブジェクトは、ユーザーがログインしている状態を表現し、この状態を利用することでログイン後の操作を制御することが可能になります。

○ステップ4:ログイン機能の実装

さて、ログイン機能を実装するために、ログインフォームとセッションの準備ができました。次は、これらを用いてログイン機能を実装します。

ログイン機能の主な作業は、ユーザーが入力したユーザーネームとパスワードを確認し、それが正しいものであればセッションを作成してユーザーをログイン状態にする、という流れです。

□サンプルコード4:ログイン機能の実装

class LoginController
  def login(form)
    user = User.find_by_username(form.username)
    if user && user.password == form.password
      Session.new(user)
      puts "ログインに成功しました!"
    else
      puts "ユーザーネームかパスワードが間違っています。"
    end
  end
end

このコードではLoginControllerというクラスを作成し、その中にloginというメソッドを定義しています。

loginメソッドは、LoginFormのインスタンスを引数に取り、User.find_by_usernameメソッドを使ってユーザーネームが一致するUserのインスタンスを探します。

見つかったユーザーのパスワードがフォームのパスワードと一致していれば、新たなSessionのインスタンスを作成し、ログイン成功のメッセージを出力します。

一致しなければ、エラーメッセージを出力します。

ログイン機能の実装コードを実行すると、次のような結果を得られます。

user = User.new("username", "password")
form = LoginForm.new("username", "password")
controller = LoginController.new
controller.login(form) # "ログインに成功しました!"と出力される

以上の例では、正しいユーザーネームとパスワードをLoginFormに入力した結果、ログインに成功しました、というメッセージが出力されました。

○ステップ5:ログアウト機能の実装

ログイン機能と同様に、ログアウト機能も必要です。

ログアウト機能は、現在のセッションを破棄することでユーザーのログアウト状態を表現します。

□サンプルコード5:ログアウト機能の実装

class Session
  attr_accessor :user

  def initialize(user)
    @user = user
  end

  def logout
    @user = nil
    puts "ログアウトしました!"
  end
end

このコードではSessionクラスにlogoutメソッドを追加しています。

このlogoutメソッドは、@userをnilに設定し、セッションからユーザーの情報を削除することでログアウトを実現します。

ログアウトが成功したら、その旨のメッセージを出力します。

このログアウト機能のコードを実行すると、次のような結果を得られます。

user = User.new("username", "password")
session = Session.new(user)
session.logout # "ログアウトしました!"と出力される

以上の例では、Sessionのインスタンスに対してlogoutメソッドを実行した結果、ログアウトしました、というメッセージが出力されました。

これにより、ログイン状態からログアウト状態への変更が可能となりました。

ここまでのステップで、Rubyを用いて基本的なログインとログアウト機能を実装する方法を学びました。

しかし、これだけではまだ安全にユーザーの情報を保管するためのセキュリティ対策が不足しています。

●ログイン機能の応用

Rubyを使ったログイン機能の実装は、これで基本的には完了ですが、セキュリティ対策が欠かせません。

パスワードをそのまま保存すると、万が一データベースが攻撃を受けた際にパスワードが盗まれる可能性があります。

これを防ぐためにパスワードのハッシュ化が一般的に行われます。

○パスワードのハッシュ化

パスワードのハッシュ化とは、パスワードを特定の計算処理を通して生成される固有の文字列(ハッシュ値)に変換することです。

ハッシュ化されたパスワードは元のパスワードに戻すことができません。

これにより、パスワードが漏洩しても、実際のパスワードは盗まれず、ユーザーの情報は安全に保たれます。

□サンプルコード6:パスワードのハッシュ化

require 'digest'

class User
  attr_accessor :username, :password

  def initialize(username, password)
    @username = username
    @password = Digest::SHA256.hexdigest(password)
  end
end

このコードでは、DigestモジュールのSHA256ハッシュ関数を使ってパスワードをハッシュ化しています。

ユーザーがパスワードを入力すると、そのパスワードはハッシュ化されて保存されます。

これにより、パスワードは安全に保管されます。

このパスワードハッシュ化のコードを実行すると、次のような結果を得られます。

user = User.new("username", "password")
puts user.password # ハッシュ化されたパスワードが出力される

以上の例では、新たにユーザーを作成した際にパスワードがハッシュ化されて保存され、そのハッシュ値が出力されました。

○セッションハイジャック対策

次に重要なセキュリティ対策として、セッションハイジャック対策を紹介します。

セッションハイジャックとは、不正な第三者がユーザーのセッションIDを盗み、そのユーザーとして振る舞う攻撃方法です。

これを防ぐためには、ログイン成功後にセッションIDを更新する方法があります。

□サンプルコード7:セッションハイジャック対策

class Session
  attr_accessor :session_id, :user

  def initialize(user)
    @session_id = generate_session_id
    @user = user
  end

  def login(user)
    @user = user
    @session_id = generate_session_id
    puts "ログインしました!"
  end

  def logout
    @user = nil
    puts "ログアウトしました!"
  end

  private

  def generate_session_id
    SecureRandom.hex(10)
  end
end

このコードでは、SecureRandomモジュールのhexメソッドを使って新たなセッションIDを生成しています。

これにより、ログインするたびにセッションIDが新しくなり、セッションハイジャックのリスクを軽減できます。

このセッションハイジャック対策のコードを実行すると、次のような結果を得られます。

user = User.new("username", "password")
session = Session.new(user)
puts session.session_id # 新しいセッションIDが出力される

以上の例では、新たなSessionのインスタンスを作成した際に、新しいセッションIDが生成されて出力されました。

また、ユーザーがログインするたびに、セッションIDが新しくなることで、セッションハイジャックの防止につながります。

●ログイン機能のカスタマイズ方法

ここまでRubyでのログイン機能の基本的な実装とセキュリティ対策について学びました。

次に、より便利なログイン機能を作るためのカスタマイズ方法を見ていきましょう。

まずは、ログイン状態の維持について見ていきましょう。

○ログイン状態の維持

ユーザーが一度ログインした後も、そのログイン状態を一定期間維持する機能は、ユーザーの利便性を高めます。

□サンプルコード8:ログイン状態の維持

class Session
  attr_accessor :session_id, :user, :expiry

  def initialize(user)
    @session_id = generate_session_id
    @user = user
    @expiry = Time.now + 3600 # 1時間後にセッションが切れる
  end

  def valid?
    Time.now <= @expiry
  end

  private

  def generate_session_id
    SecureRandom.hex(10)
  end
end

このコードでは、Sessionクラスにexpiryという新たなインスタンス変数を追加し、これを利用してセッションの有効期限を設定しています。

そして、valid?メソッドを使用して現在の時間がexpiryよりも前であればセッションが有効、そうでなければ無効となるようにしています。

このログイン状態の維持のコードを実行すると、次のような結果を得られます。

user = User.new("username", "password")
session = Session.new(user)
puts session.valid? # 有効期限が切れていなければtrueが出力される

以上の例では、新たなSessionのインスタンスを作成した際に有効期限が設定され、それが切れていなければtrueが出力されました。

次に、更にセキュリティを強化するための2段階認証の追加方法を見ていきましょう。

○2段階認証の追加

2段階認証は、一度目の認証(例えば、ユーザー名とパスワードによる認証)の後に、二度目の認証を行うことで、更なるセキュリティ強化を図る方法です。

□サンプルコード9:2段階認証の追加

class User
  attr_accessor :username, :password, :mobile_number, :verification_code

  def initialize(username, password, mobile_number)
    @username = username
    @password = password
    @mobile_number = mobile_number
    @verification_code = nil
  end

  def generate_verification_code
    @verification_code = rand(1000..9999)
    # 実際のアプリケーションでは、ここでSMSを送信する処理を書く
  end

  def verify(code)
    if code == @verification_code
      puts "認証成功!"
      true
    else
      puts "認証失敗..."
      false
    end
  end
end

このコードでは、Userクラスにmobile_numberとverification_codeという2つの新たなインスタンス変数を追加しています。

そして、generate_verification_codeメソッドで4桁のランダムな認証コードを生成し、これを検証するverifyメソッドを追加しています。

これにより、ユーザー名とパスワードによる一段目の認証に成功した後、携帯電話に送られてきた認証コードによる二段目の認証を行うことができます。

この2段階認証のコードを実行すると、次のような結果を得られます。

user = User.new("username", "password", "090-1234-5678")
user.generate_verification_code
puts user.verify(1234) # ランダムに生成された認証コードが1234であればtrueが出力される

以上の例では、新たなUserのインスタンスを作成し、認証コードを生成した後、それを検証しています。

ランダムに生成された認証コードが正しければtrueが出力されます。

まとめ

Rubyでログイン機能を作成するための重要なポイントを再度強調します。

①ユーザー認証

ユーザー名とパスワードを使ってユーザーを正しく認証します。

パスワードはハッシュ化することで、元のパスワードが漏えいするリスクを軽減します。

②セッション管理

ログイン成功後は、ユーザーが認証済みであることをセッション情報で保持します。

これにより、ユーザーはログイン状態を維持することができます。

③ログイン状態の維持

ユーザーがログアウトするまで、または一定期間経過するまでログイン状態を維持する機能を実装します。

これによりユーザーは何度もログインする手間を省くことができます。

④2段階認証

一段目の認証(ユーザー名とパスワードによる認証)の後に二度目の認証を行うことで、更なるセキュリティを確保します。

二段階認証では、たとえ一段目の認証情報が漏れたとしても、二段目の認証が必要なため不正ログインを防ぐことができます。

以上のポイントを心がけながら、Rubyでログイン機能を作成すると、ユーザーに安心して使ってもらえる安全なWebアプリケーションを開発することができます。

Rubyはその簡潔な文法と高い生産性から、初心者にも扱いやすい言語とされています。

しかし、その便利さを活かしながらも、ユーザーのデータを守るためにはセキュリティに配慮する必要があります。

今回学んだログイン機能の実装方法を、ぜひともあなたのアプリケーション開発に活かしてください。

ここまでRubyでのログイン機能の実装について解説してきましたが、ここで紹介した方法はあくまで一例です。

セキュリティは絶えず新たな脅威が生まれてくる分野なので、最新の情報を常にチェックし、最適な対策を施すことが大切です。

Rubyを始めたばかりのあなたも、これからログイン機能を作ってみようというあなたも、この記事が一助となれば幸いです。

どんなアプリケーションも、その一部としてのログイン機能がユーザー体験に大きく影響します。

ぜひ、学んだ知識を活かして素晴らしいアプリケーションを作成してください。