RailsでClearanceを使った認証機能の実装方法
Clearanceは、Thoughtbotチームによって開発された、メールアドレスとパスワードによるシンプルな認証システムです。独自のデフォルト設定を持っていますが、必要に応じて簡単に上書きできるよう設計されています。また、現在も活発にメンテナンスされており、GitHubで最新の動向を確認できます。
本チュートリアルでは、RailsアプリケーションにClearanceを統合する手順を解説します。小規模なサンプルアプリケーションを作りながら進めていきましょう。それでは始めます!
はじめに
まずはRailsアプリケーションを生成します。このチュートリアルでは、アプリ名をtutsplus-clearanceとします。
rails new tutsplus-clearance -T
これでアプリの雛形が完成しました。
次に、アプリの見た目を整えるためにBootstrapを導入します。GemfileにBootstrapのgemを追加しましょう。
#Gemfile ... gem 'bootstrap-sass'
以下のコマンドでgemをインストールします。
bundle install
続いて、application.scssを以下のように編集してください。
#app/assets/stylesheets/application.scss @import 'bootstrap-sprockets'; @import 'bootstrap';
Clearanceのセットアップ
Gemfileを開いて、Clearanceのgemを追加します。
#Gemfile gem 'clearance'
gemをインストールしたら、ジェネレータコマンドを実行してClearanceをインストールします。
bundle install
rails generate clearance:install
コマンドを実行すると、ターミナルに以下のような出力が表示されます。
create config/initializers/clearance.rb
insert app/controllers/application_controller.rb
create app/models/user.rb
create db/migrate/20161115101323_create_users.rb
*******************************************************************************
Next steps:
1. Configure the mailer to create full URLs in emails:
# config/environments/{development,test}.rb
config.action_mailer.default_url_options = { host: 'localhost:3000' }
In production it should be your app's domain name.
2. Display user session and flashes. For example, in your application layout:
<% if signed_in? %>
Signed in as: <%= current_user.email %>
<%= button_to 'Sign out', sign_out_path, method: :delete %>
<% else %>
<%= link_to 'Sign in', sign_in_path %>
<% end %>
<div id="flash">
<% flash.each do |key, value| %>
<div class="flash <%= key %>"><%= value %></div>
<% end %>
</div>
3. Migrate:
rake db:migrate
*******************************************************************************
コマンドを実行すると、アプリ内にいくつかのファイルが生成されます。そのひとつがconfig/initializersディレクトリにあるclearance.rbです。また、Userモデルも生成され、同時に以下のようなマイグレーションファイルも作成されます。
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.timestamps null: false
t.string :email, null: false
t.string :encrypted_password, limit: 128, null: false
t.string :confirmation_token, limit: 128
t.string :remember_token, limit: 128, null: false
end
add_index :users, :email
add_index :users, :remember_token
end
end
出力内容に従い、まずは環境設定ファイルを編集しましょう。config/environments/development.rbを開き、endの直前に以下の行を追加します。
...
config.action_mailer.default_url_options = { host: 'localhost:3000' }
end
次に、config/initializers/clearance.rbを開き、送信元メールアドレスをデフォルトから任意のものに変更します。ファイルを開くと、以下のような記述が確認できます。
#config/initializers/clearance.rb Clearance.configure do |config| config.mailer_sender = "reply@example.com" end
デフォルト設定を上書きしたい場合は、以下のコードスニペットを貼り付けて、自分の要件に合わせて設定を変更できます。
#config/initializers/clearance.rb
Clearance.configure do |config|
config.allow_sign_up = true
config.cookie_domain = ".example.com"
config.cookie_expiration = lambda { |cookies| 1.year.from_now.utc }
config.cookie_name = "remember_token"
config.cookie_path = "/"
config.routes = true
config.httponly = false
config.mailer_sender = "reply@example.com"
config.password_strategy = Clearance::PasswordStrategies::BCrypt
config.redirect_url = "/"
config.secure_cookie = false
config.sign_in_guards = []
config.user_model = User
end
データベースをマイグレーションするコマンドを実行します。
rake db:migrate
PagesControllerを開き、indexアクションを追加しましょう。
#app/controllers/pages_controller.rb class PagesController < ApplicationController def index end end
次に、先ほど作成したindexアクション用のビューを作成します。
以下のコードを追加してください。
#app/views/pages/index.html.erb <h1>Tutsplus Clearance</h1> <p>Welcome to our Clearance Page.</p>
ルーティングを以下のように編集します。
#config/routes.rb Rails.application.routes.draw do root to: "pages#index" end
続いて、layoutsディレクトリ内に_navigation.html.erbというパーシャルを作成します。これは、アプリのナビゲーション関連の処理をまとめるために使用します。
以下のコードを貼り付けて保存してください。
#app/views/layouts/_navigation.html.erb
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<%= link_to 'Tutsplus-Clearance', root_path, class: 'navbar-brand' %>
</div>
<div id="navbar">
<% if signed_in? %>
<ul class="nav navbar-nav">
<li><%= link_to 'Add Page', new_page_path %></li>
</ul>
<% end %>
<ul class="nav navbar-nav pull-right">
<% if signed_in? %>
<li><span><%= current_user.email %></span></li>
<li><%= link_to 'Sign out', sign_out_path, method: :delete %></li>
<% else %>
<li><%= link_to 'Sign in', sign_in_path %></li>
<% end %>
</ul>
</div>
</div>
</nav>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
<%= value %>
</div>
<% end %>
</div>
アクセス制限
Clearanceを使えば、アプリ内の特定ページへのアクセスを制限することができます。具体的な実装方法を見ていきましょう。
app/views/pagesディレクトリに、newアクション用のビューとしてnew.html.erbというファイルを作成し、以下のコードを貼り付けます。
#app/views/pages/new.html.erb <h1>Restricted Page</h1> <p>This page is restricted to authenticated users, if you can see this it means you are a superstar!</p>
次に、config/routes.rbに以下の行を追加します。
#config/routes.rb ... resources :pages, only: :new ...
最後に、PagesControllerを以下のように編集します。
#apps/controllers/pages_controller.rb class PagesController < ApplicationController before_action :require_login, only: [:new] def index end def new end end
上記のコードでは、Clearanceが提供するヘルパーrequire_loginを使用して、newアクションへのアクセスを制限しています。動作を確認するには、ターミナルでrails serverを実行してRailsサーバーを起動し、ブラウザでhttps://locahost:3000/pages/newにアクセスしてみてください。サインインページへリダイレクトされるはずです。
さらに、Clearanceにはアクセス制御に使えるルーティング制約も用意されています。
#config/routes.rb
Rails.application.routes.draw do
constraints Clearance::Constraints::SignedOut.new do
root to: 'pages#index'
end
constraints Clearance::Constraints::SignedIn.new do
root to: "pages#new', as: :signed_in_root
end
end
上記のコードでは、認証済みユーザー向けに別のルートが定義されています。
Clearanceのデフォルト設定を上書きする
Clearanceを使い始めると、見えないところでさまざまな処理が自動的に行われます。アプリの仕様によっては、これらを独自にカスタマイズしたくなる場面もあるでしょう。Clearanceでは、デフォルトの設定を自由に上書きできます。
Clearanceのルートを上書き(または生成)するには、ターミナルで以下のコマンドを実行します。
rails generate clearance:routes
すると、ルーティングファイルは以下のようになります。
#config/routes.rb
Rails.application.routes.draw do
resources :passwords, controller: "clearance/passwords", only: [:create, :new]
resource :session, controller: "clearance/sessions", only: [:create]
resources :users, controller: "clearance/users", only: [:create] do
resource :password,
controller: "clearance/passwords",
only: [:create, :edit, :update]
end
get "/sign_in" => "clearance/sessions#new", as: "sign_in"
delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out"
get "/sign_up" => "clearance/users#new", as: "sign_up"
root to: "pages#index"
resources :pages, only: :new
end
このコマンドを実行すると、config/initializers/clearance.rb内のconfig.routes設定がfalseに変更されます。これにより、新しく生成されたカスタムファイルが使用されるようになります。
ビューを生成して編集可能にするには、以下のコマンドを実行します。
rails generate clearance:views
生成される主なファイルは以下の通りです。
app/views/passwords/create.html.erb app/views/passwords/edit.html.erb app/views/passwords/new.html.erb app/views/sessions/_form.html.erb app/views/sessions/new.html.erb app/views/users/_form.html.erb app/views/users/new.html.erb config/locales/clearance.en.yml
ターミナルに、app/views/layouts/application.html.erbファイルを上書きするかどうかを尋ねるプロンプトが表示されます。任意のオプションを選択してください。
レイアウト
デフォルトでは、Clearanceはアプリケーションのデフォルトレイアウトを使用します。Clearanceがビューを描画する際に使用するレイアウトを変更したい場合は、イニシャライザでレイアウトを指定するだけでOKです。
Clearance::PasswordsController.layout "my_passwords_layout" Clearance::SessionsController.layout "my_sessions_layout" Clearance::UsersController.layout "my_admin_layout"
ヘルパーメソッド
Clearanceは、controllers、views、helpersで使用できる便利なヘルパーメソッドを提供しています。代表的なものとしては、signed_in?、signed_out?、current_userなどがあります。使用例は以下の通りです。
<% if signed_in? %> <%= current_user.email %> <%= button_to "Sign out", sign_out_path, method: :delete %> <% else %> <%= link_to "Sign in", sign_in_path %> <% end %>
まとめ
Clearanceは認証機能に関して多くの機能を提供してくれる強力なツールです。ぜひ次のプロジェクトで試してみてください。さらに詳しく知りたい方は、GitHubページをチェックしてみましょう。
-
Railsのセキュリティ脅威に立ち向かう:認証と機密データ露出への対策
本シリーズの第1回では、インジェクション攻撃について解説しました。 OWASP Top 10 Webアプリケーションセキュリティリスクをテーマにした本シリーズの第2回となる今回は、認証の不備と機密データの露出という脅威の世界を深く掘り下げていきます。 具体的には、ハッカーがどれほど簡単にあなたが書いたコードを欺き、ユーザーのデータを盗み出すことができるのか、以下のような攻撃手法を見ていきます。 ユーザー列挙(User Enumeration):ログインページを悪用し、候補となるユーザー名のリストを総当たりで試して、データベース内にそのユーザーが存在するかどうかを確認する攻撃。 弱いパスワード
-
Rails5でのAngularの使用
あなたは前にその話を聞いたことがあります。分散型で完全に機能するバックエンドAPIと、通常のツールセットで作成されたフロントエンドで実行されているアプリケーションがすでにあります。 次に、Angularに移動します。または、AngularをRailsプロジェクトと統合する方法を探しているだけかもしれません。これは、この方法を好むためです。私たちはあなたを責めません。 このようなアプローチを使用すると、両方の世界を活用して、たとえばRailsとAngularのどちらの機能を使用してフォーマットするかを決定できます。 構築するもの 心配する必要はありません。このチュートリアルは、この目的のた