Basic認証
Basic認証とは
Basic認証
Basic認証
とは、HTTP通信の規格に備え付けられているユーザー認証の仕組み。
サーバーと通信が可能なユーザーとパスワードをあらかじめ設定しておき、それを知っているユーザーのみがWebアプリーションを利用できるようにすることができる。
Ruby on Railsには、Basic認証を導入するためのメソッドが用意されており、簡単に実装することができる。
authenticate_or_request_with_http_basic
Ruby on RailsでBasic認証を実装するためのメソッド。
ブロックを開き、ブロック内部でusernameとpasswordを設定することでBasic認証を利用できる。
1 2 3 4 |
# 'admin'というユーザー名と、'password'というパスワードでBasic認証できるように設定
authenticate_or_request_with_http_basic do |username, password|
username == 'admin' && password == 'password'
end
|
Basic認証のRailsアプリケーションへの導入
authenticate_or_request_with_http_basic
メソッドを利用して、開発中のRailsアプリケーションにBasic認証を導入する。
RailsアプリケーションにBasic認証を導入
Basic認証によるログインの要求は、全てのコントローラで行いたい。そこで、Basic認証の処理をapplication_controller.rbにて、private以下にメソッドとして定義し、before_actionで呼び出すように実装する。
1 2 3 4 5 6 7 8 9 10 11 |
class ApplicationController < ActionController::Base
before_action :basic_auth
private
def basic_auth
authenticate_or_request_with_http_basic do |username, password|
username == 'admin' && password == '2222'
end
end
end
|
これで、どのページにアクセスしてもBasic認証が要求されるようになる。今回は、adminというユーザー名と2222というパスワードでBasic認証ができるように設定している。
Basic認証の動作を確認する
application_controller.rbの記述が完了したら、実際にアプリケーションを起動し、Basic認証の動作が期待したものになっているか確認。
'rails s'をした上で、適当なページにアクセスすると、ユーザー名とパスワードの入力を求めるポップアップウインドウが表示される。間違ったユーザー名とパスワードではBasic認証できないことを確かめるために、あえて適当な文字を入力。以下のGifでは、ユーザー名にhogehoge、パスワードに1111と入力している。
正しく実装できていれば、もう一度Basic認証用のポップアップウインドウが表示される。 間違った情報ではログインできないことを確認できたので、今度は正しい情報を入力してログインできるかどうかを確かめてみる。ユーザー名にadmin、パスワードに2222と入力して、もう一度ログインを試みる。
ルーティングに対応したページが表示されれば、Basic認証に成功。
Basic認証のコードを改良する
ここまでの実装で、Basic認証をRailsアプリケーションに導入することができた。しかし、現状のコードには次の2つの問題点がある。
(1)ユーザー名・パスワードがコードに記述されている
Basic認証をするための、adminというユーザー名と、そのパスワード2222がコードに記述されている。もしもGithub上の公開リポジトリでソースコードを管理している場合、コードを読める何者かに不正にBasic認証を突破されてしまう。対策として、コードに直接ユーザー名とパスワードを記述するのではなく、環境変数を利用する実装に切り替えることが考えられる。
(2)全ての環境でBasic認証を要求してしまう
Basic認証を使ってアクセスを制限したいのは、アプリケーションがデプロイされている本番環境でだけのはずだが、現在のコードでは、basic_authメソッドを使いたい環境を特に指定していないため、本番環境・テスト環境・開発環境の全てでBasic認証が働いてしまう。開発中にいちいちBasic認証をするのは煩わしいので、本番環境のみでBasic認証をするようにコードを書き換える。
ユーザー名・パスワードを環境変数にする
basic_authメソッド内で直接記述しているユーザー名とパスワードを環境変数に格納する。
ローカル環境の設定
1 2 3 4 5 6 7 8 9 10 11 |
本番環境の設定
1 2 3 4 5 6 7 8 9 10 |
1 2 3 4 5 6 7 |
BASIC_AUTH_USER
とBASIC_AUTH_PASSWORD
という名前で、それぞれユーザー名とパスワードを定義することができた。続いて、この環境変数をRailsアプリケーション側で読み込むように記述変更する。
1 2 3 4 5 6 7 8 9 10 11 12 |
class ApplicationController < ActionController::Base
before_action :basic_auth
protect_from_forgery with: :exception
private
def basic_auth
authenticate_or_request_with_http_basic do |username, password|
username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
end
end
end
|
これで、環境変数を使って、Basic認証を行えるユーザー名とパスワードを定義することができた。もう一度Basic認証を試みて、環境変数として設定したユーザー名とパスワードでログインができれば、正しく実装できている。
環境変数は、環境ごとに設定する必要がある。開発環境でBasic認証をしたい場合はローカルの~/.bash_profileを、本番環境でBasic認証をしたい場合は本番サーバーにssh接続して、~/.bash_profileを編集する。
Capistranoを利用して自動デプロイを行う場合、環境変数を明示的に指定する必要がある。config/deploy.rbに追記する。
本番環境のみでBasic認証をするように実装する
まずはconfig/deploy配下のproduction.rbに追記。(すでに追加済なら作業不要)
1 2 3 4 5 6 7 8 |
# server "db.example.com", user: "deploy", roles: %w{db}
server "(EC2のIPアドレス)", user: "ec2-user", roles: %w{app db web}
set :rails_env, "production"
set :unicorn_rack_env, "production"
# role-based syntax
# ==================
|
これで、unicornが現在の環境を本番環境として認識するようになる。
さらにapplication_controllerの記述を少し変更する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class ApplicationController < ActionController::Base
before_action :basic_auth, if: :production?
protect_from_forgery with: :exception
private
def production?
Rails.env.production?
end
def basic_auth
authenticate_or_request_with_http_basic do |username, password|
username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
end
end
end
|
production?
というメソッドを定義し、現在の環境が本番環境ならtrue、そうでないならfalseを返すように、Rails.env.production?と記述している。そして、before_action :basic_auth の後に、 if: :production?と記述することによって、本番環境のみでbasic_authメソッドが実行されるようになる。
Basic認証の動作確認を行う
続いて、Basic認証の動作確認をする。Basic認証を実装したブランチをマージしたら、Capistranoを用いたデプロイを行う。初めてBasic認証の動作確認をする時だけ、以下のようにデプロイをしてunicornの停止と起動も行ってから動作確認する。
1 2 3 4 |
もしうまく動かない場合は、一度AWSのコンソールからEC2を再起動し、nginx、MySQL、Unicornを手動で順番に再起動。
なおUnicornは以下のように起動する。
1 2 |
Basic認証の問題点
Basic認証は少ない手間で認証を実現できるので、便利なのだが、安全性という観点から、完全に信頼できる認証方式ではない。HTTP通信で定義されている仕様上、ユーザー名とパスワードが通信経路上にそのまま送られるため、漏洩のリスクがある。また、ログアウトの概念が定義されていないため、もし必要になる場合は自力で実装する必要があるほか、複数のサーバーを跨いだ認証が難しいといった特徴も問題になりうる。
あくまで、必要最低限の認証機能を作成中のWebアプリケーションに実装したい場合のみ、Basic認証を利用するようにする。
参考リンク
https://ja.wikipedia.org/wiki/Basic%E8%AA%8D%E8%A8%BC
Basic認証はHTTPで定義されている認証方法。どのようなリクエスト・レスポンスを送っているのかがわかる。
・Rails.env リファレンス(英語)
https://apidock.com/rails/Rails/env/class
Rails.envについて、具体的な説明はないが、コード例が載っている。