1707736774
2024-02-12 09:37:46
承認とは、現在のユーザーに一部の URL (より一般的には、あらゆる種類のリソース) へのアクセスを許可または拒否することを意味します。
これは認証と密接に関係していますが、異なります。
気候変動に関する国際会議について考えてみましょう。
認証は入場券であり、チケットがなければカンファレンスに入場することはできません。
承認とは、アクセスのチケット レベルを確認することです。ゲート A またはスナック B へのアクセスを許可しますか?
Rails 7 での認証
Rails は認証用のジェネレーターを推奨しているようです (Rails 8 ではそうなるでしょう) ので、(現時点では) 最も近い可能性である auth-zero ジェネレーターを使用してみましょう。
前提条件
このチュートリアルで使用するツール
1
2
3
4
5
ruby -v # 3.3.0
rails -v # 7.1.3
bundle -v # 2.4.10
node -v # 20.9.0
git --version # 2.34.1
認可・認証前
Rails は認証用のジェネレーターを推奨しているようです (Rails 8 ではそうなるでしょう) ので、(現時点では) 最も近い可能性である auth-zero ジェネレーターを使用してみましょう。
それでは、認証システム (CSS なし) を構築することから始めましょう
1
2
3
4
5
rails new myapp
cd myapp
bundle add authentication-zero
bin/rails generate authentication
素晴らしい! これで、認証機能が強化されたデフォルトの Rails アプリが完成しました。
データベースをシードして作成する
db/seeds.rb 内
1
User.create(email: "[email protected]", password_digest: BCrypt::Password.create("Secret1*3*5*"), verified: true)
次にデータベースを作成します
1
2
3
4
5
6
# Create database and schema.rb
bin/rails db:create
bin/rails db:migrate
bin/rails db:seed
そしてサーバーを起動します:
1
2
# Launch the local web server
bin/rails server
良い! 次に、localhost:3000 を開き、seed.rb 内にあるユーザーで認証を試みます。
ここでログアウトし、ローカル Web サーバーを停止します。
3 つの異なるページを作成する
次に、ホームページ、プロフィール ページ、管理者ページの 3 つの異なるページを作成しましょう。
このようなようこそページ:
1
2
3
4
5
echo "class WelcomeController < ApplicationController" > app/controllers/welcome_controller.rb
echo "end" >> app/controllers/welcome_controller.rb
mkdir app/views/welcome
echo 'welcome page
' > app/views/welcome/index.html.erb
このようなプロフィールページ:
1
2
3
4
5
echo "class ProfileController < ApplicationController" > app/controllers/profile_controller.rb
echo "end" >> app/controllers/profile_controller.rb
mkdir app/views/profile
echo 'Profile page
' > app/views/profile/index.html.erb
そして、次のような管理ページ:
1
2
3
4
5
echo "class AdminController < ApplicationController" > app/controllers/admin_controller.rb
echo "end" >> app/controllers/admin_controller.rb
mkdir app/views/admin
echo 'Admin only area!
' > app/views/admin/index.html.erb
次に、これらの新しいページにルートを適用します。
1
2
3
4
5
6
7
8
9
10
11
12
# inside config/routes.rb
Rails.application.routes.draw do
# add these 3 lines
get "welcome", to: "welcome#index"
get "profile", to: "profile#index"
get "admin", to: "admin#index"
# all other routes remain unchanged
# ...
end
ローカル Web サーバーを再起動し、次の URL にアクセスしてみます。
- 「http://locahost:3000/welcome」、ウェルカムページ
- 「http://locahost:3000/profile」、プロフィールページ
- 「http://locahost:3000/admin」、管理者専用エリア 😉
うわぁ! ログイン画面を通過しない限り、いずれも使用できません。
多くの Rails プロジェクトで見られる良い実践は、すべてのルートをデフォルトで「認証」することです。つまり、すでに認証されていない限り、ルートにアクセスすることはできません。
ページを一般公開する
HomeController を次のように変更します。
1
2
3
4
5
6
# Inside app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
skip_before_action :authenticate # add this
end
なるほど、公平ですね。 認証が必要なウェルカム ページはほとんど表示されません。
そこで、もう一度ようこそページ (http://locahost:3000/welcome) を開くと、認証を必要とせずにアクセスできるようになります。
役割列を追加
承認は認証にリンクされていますが、まったく同じものではないことに注意してください。
- 単純な訪問者はホームページを表示できますが、ユーザー プロフィール ページにはアクセスできません。
- ユーザーはホームページとプロフィール ページにアクセスできますが、管理ダッシュボードにはアクセスできません
- 管理者はアプリケーションのあらゆる部分にアクセスできます
したがって、それを知るためには「役割」列が必要です。 誰が にアクセスできます 何
ローカル Web サーバーを停止します
ターミナルに戻り、次のように入力します。
1
bin/rails generate migration add_role_to_users role:string
移行ファイルを次のように変更します。
1
2
3
4
5
6
class AddRoleToUsers < ActiveRecord::Migration
def change
# modify as follow
add_column :users, :role, :string, :default => "customer"
end
end
そして走ります
user.rb 内
1
2
3
4
5
6
7
8
class User < ApplicationRecord
has_secure_password
# add this line
enum role: {customer: "customer", admin: "admin"}
# ...rest of code
end
データベースにさまざまなプロファイルをシードする
db/seeds.rb 内
1
2
3
User.create(email: "[email protected]", role: 'customer', password_digest: BCrypt::Password.create("Secret1*3*5*"), verified: true)
User.create(email: "[email protected]", role: 'customer', password_digest: BCrypt::Password.create("Secret1*3*5*"), verified: true)
User.create(email: "[email protected]", role: 'admin', password_digest: BCrypt::Password.create("Secret1*3*5*"), verified: true)
データベースを再作成します (実稼働データベースを作成したら、通常はこれを行いませんが、小規模なチュートリアルの場合は問題ありません)。
1
bin/rails db:drop db:create db:migrate db:seed
次のコマンドでローカル Web サーバーを再起動します。
そして、[email protected] として接続し、localhost:3000/admin にアクセスしてみます。
うわぁ! 顧客として接続した場合でも、管理エリアにアクセスできます。 認証エラーが発生するはずなので、今度は Pundit で認証を行います。
Pundit による Rails 7 の認可 (ついに!)
Pundit を追加して、権限のないユーザーが派手な Web アプリ内のあらゆる場所にアクセスすることを明確に防止します。
追加 gem 'pundit' Gemfile へ:
そして走ります
アプリケーション コントローラーに Pundit を含めます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ApplicationController < ActionController::Base
include Pundit::Authorization # add this line
# was here before, left as-is
before_action :set_current_request_details
before_action :authenticate
# add this method, required by Pundit
def current_user
Current.user # this belongs to the authentication mechanism, so not Pundit
end
# rest of code ...
end
また、ジェネレーターを実行して、いくつかの便利なデフォルトを使用してアプリケーション ポリシーをセットアップすることもできます。
1
bin/rails g pundit:install
その後、Rails サーバーを再起動する必要があります。 Rails は新しいクラスのあらゆるクラスを選択できるようになりました。 app/policies/ ディレクトリ。
ポリシーの追加
1
2
touch app/policies/admin_policy.rb
私たちの admin_policy.rb 管理者のみが管理ダッシュボードにアクセスできるようにします。
1
2
3
4
5
6
7
class AdminPolicy < ApplicationPolicy
attr_reader :user
def index?
return user.admin?
end
end
Pundit ポリシーをコントローラーに挿入する
それでは、ポリシーをコントローラーに注入しましょう。
1
2
3
4
5
6
7
class AdminController < ApplicationController
def index
authorize Current.user, policy_class: AdminPolicy
end
end
わーい! ここでは Rails の魔法はあまり必要ありません。 現在のユーザーに特定のポリシーを明示的に許可します。
次に、Web サーバーを再起動し、顧客として管理エリアに接続してみます。 エラーが発生するはずです。
管理者として管理領域に接続してみます。 正しく動作するはずです:)
それはどのくらい良いですか?
まとめ
Web アプリの 2 つの主要な概念をゼロから説明しました。
- ジェネレーターを使用した認証: Rails 8 は次のように動作するため、これを実現するために同様の gem に依存しました。
- どのユーザーがどのリソースにアクセスできるかを知るための、よく知られた gem を使用した承認。
それでは良い一日をお過ごしください:)
デビッド
#Rails #での認証と認可