タイトルの通りである。rails new
で新規にアプリケーションを立ち上げ、Herokuで最初のデプロイするとこまでは問題なく完遂できたが、その後に環境変数を使用してローカルにBasic認証を導入しようとしたらうまくいかなかった。ダイアログが表示されない。環境変数を使わずにapplication_controller.rb内にユーザー名とパスワードを直接設定しても同じ。一つ前の自分の記事に載せている内容も含め、考えられるありとあらゆる方法を全て試したが駄目だった...。
また、ローカルによる動作確認後も、今度はリモートで同じくBasic認証のダイアログが表示されなかった。
結論
application_controller.rb内にBasic認証用の処理を記述しただけで、継承先のコントローラファイルを何も生成していないのが原因だった。リモート環境に関して言えば、masterブランチに最新のコミットをプッシュしてheroku config:set
コマンドで設定した環境変数をきちんと反映させれば解決した。
前提条件
- macOS Catalina ( 10.15.7 )
- Visual Studio Code.app( 1.59.1 )
- Terminal.app ( 2.10 )
- Rails ( 6.0.4.1 )
- Heroku ( 7.59.0 darwin-x64 node-v12.21.0 )
- Vivaldi.app ( 4.1.2369.21 (Stable channel) x86_64 )
※執筆時のバージョン
本題
ローカル環境での動作確認
ヒントになりそうなこちらの記事を発見。
おや、認証されない。。。
と焦らないでも大丈夫です。
今回application_controller.rbに実装したBasic認証を継承しているコントローラはscaffoldで作成したusers_controller.rbのみです。
また、定義されているルーティングはRESTfulなusersリソースのみです。
上記からBasic認証の挙動を確認出来るのはhttp://localhost:3000/users/配下のURLのみになります。
言い換えると、application_controller.rbに実装したBasic認証を継承しているコントローラが無かったら、どこのURLにアクセスしても、認証されないどころかそもそもBasic認証自体が機能しないのではないだろうかと考えた。そこでひとまず、何でも良いからコントローラファイルを生成して、Basic認証を通すためのパスを設定してみることにした。
% rails g controller items index
上のコマンドを実行することによって、indexアクション付きコントローラファイルitems_controller.rb、及びビューファイルindex.html.erbが自動生成され、ルーティングも自動設定される1。
class ItemsController < ApplicationController
def index
end
end
<h1>Items#index</h1>
<p>Find me in app/views/items/index.html.erb</p>
Rails.application.routes.draw do
get 'items/index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
rails routes
すると、URIパターンが*/items/index*となっているから、http://localhost:3000/items/indexにアクセスしてみる。
表示された!正しいユーザー名とパスワードを入力して認証にも成功。試しにhttp://localhost:3000にもアクセスしてみる。
いつものハッピーなイラストのデフォルト画面は表示されたが、やはりルートパスに該当するコントローラとアクションを割り当ててないので、Basic認証のダイアログは表示されなかった。
application_◯◯のファイルは、全ての◯◯において共通の処理を記述する。言い換えれば、application_◯◯はそれとはまた別の各〇〇とを組み合わせて使用するので、継承元のapplication_◯◯だけファイルがあっても何の意味もない2?そのためBasic認証も、しっかりapplication_controller.rbに実装のための追記をしていたとしても、継承先のcontrollerファイルが無かったら機能しないのだ。
class ApplicationController < ActionController::Base # ApplicationControllerクラス
before_action :basic_auth
private
def basic_auth
authenticate_or_request_with_http_basic do |username, password|
username == ENV['BASIC_AUTH_USERNAME'] && password == ENV['BASIC_AUTH_PASSWORD']
end
end
end
class ItemsController < ApplicationController # application_controller.rb内のApplicationControllerクラスを継承
def index
end
end
リモート環境での動作確認
git push heroku master
等でHerokuにデプロイした後に環境変数を設定したら、一度リモート環境のプロセスを中断しなければならない。git push heroku master
を実行する度に、処理の中でHerokuが再起動される。そもそも自分は最初の一回しかデプロイしてなく、しかもその後にBasic認証を導入しようとしていたので、application_controller.rbの変更も反映されていない状態だった。また、Herokuによる環境変数の設定はmaster以外のブランチ(トピックブランチ)上で行ったので、一旦git push heroku master
で枝分かれする前のコミットまでプッシュして、その後にトピックブランチ上のコミットをプッシュする。
現行トピックブランチで作業していても、念の為にGitの変更履歴順を考慮してプッシュするのが良さげ。トピックブランチ上のコミットを先にプッシュすると、枝分かれ(トピックブランチ作成)前段階のコミットが反映されない可能性があるからだ(未検証)。チームで開発するなら話は変わってくるけど...
トピックブランチ上のコミットをmasterブランチに反映させる3には、git push heroku ‘トピックブランチ名’:master
というコマンドになる。
masterブランチ上のコミットをプッシュ
% git push heroku master
Heroku上の環境変数一覧を参照して、Basic認証用の変数の値が正しく設定されていることを確認
% heroku config
トピックブランチ上のコミットをプッシュ
% git push heroku ‘トピックブランチ名’:master
これで、リモート環境でもダイアログがきちんと表示され、認証もばっちり成功した!
因みに、Heroku自体のアップデートと、Rubyのバージョンを2.6.7から2.6.8に上げよという警告メッセージが発生したので、このタイミングでこの2つも実行した♪
Basic認証は認証自体は本当にBasicだけど、実装はちょっとHardだったなぁ...まいった
参考記事
- 【Ruby on Rails】Basic認証の実装方法
- master以外のブランチからherokuにpushする方法 - Qiita
- Git を使用したデプロイ | Heroku Dev Center
関連投稿記事
-
このように、
rails g controller ‘コントローラ名’ ‘アクション名’
というコマンドで、指定したコントローラだけじゃなく、指定したアクションのルーティングを自動設定し、且つそのビューも同時生成してくれる。ただルーティングにresourcesメソッドは使われず、HTTPメソッドとURIパターンのセットで記述されるので、書き直しが必要。 ↩ -
〇〇に入るのは、controller(コントローラ)だったり、mailer(メーラー)だったり、record(モデル)だったりする。 ↩
-
Herokuはリモートのmasterブランチにプッシュするコードだけがデプロイされる。それ以外の、トピックブランチにプッシュしても意味が無いようだ。 ↩