Rails Basic認証の導入


Railsでの認証の種類

Railsで開発をして行く上では、3種類の認証タイプがあります。

  • Basic認証
  • Digest認証
  • Token認証
  • こちらの公式ページでも3種類のタイプが紹介されています。この三つを扱えればとりあえずいいのでは。

Basic認証

今回は最もシンプルなBasic認証について、手順を整理してみたいと思います。

そもそもBasic認証とはなんぞや

Basic認証とは、サーバーと通信する時にユーザー名とパスワードを知っている人じゃないと、そのサイトにアクセス出来ないようにするための機能です。

こんな感じのやつですね。

前提

  • アプリケーションサーバーはUnicornを使っているとする
  • WebサーバーはNginxを使っているとする
    クラウドはAWSを使っているとする

  • Capistranoを用いて自動デプロイをしているとする

application_controllerにメソッドを書く

Basic認証は全てのコントローラで行いたいので、application_controller.rbにコードを書いていきます!
RailsにはBasic認証をするためのメソッドが用意されています。
それがauthenticate_or_request_with_http_basicです!

app/controllers/application_controller.rb
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

authenticate_or_request_with_http_basicはRailsで簡単にBasic認証を実装してくれるメソッドです
username == ENV["BASIC_AUTH_USER"]&& password == ENV["BASIC_AUTH_PASSWORD"]のところは環境変数を使用します。

直接、username="keita"とかコードに書いちゃうとGithubにミスってアップしちゃった時に確実に不正利用されます!気をつけて下さい!

ターミナルで 〜/.bash_profileに環境変数を書く

今回は本番環境のみでBasic認証が行われるようにします。

ローカル
$ vim ~/.bash_profile
 <!--「i」を押してインサートモードにいく-->

export BASIC_AUTH_USER='keita'
export BASIC_AUTH_PASSWORD='0322'
<!-- 書き終えたらescキーを押して、「:wq」を押して保存して終了-->

$ source ~/.bash_profile

<!--最後に.bash_profileを読み込んで環境変数を反映させる-->

本番環境でのみBasic認証するようにする

config/deploy/production.rbに追記していきます。

config/deploy.rb
# 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の記述を変更する

app/controllers/application_controller.rb
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

追加したのは
before_action :basic_auth, if: :production?

def production?
Rails.env.production?
end

の二つだけです。

production?メソッドでRails.env.production?を定義しているので本番環境なのかローカルなのか分かるようになっています。

最後にデプロイして動作確認

$ bundle exec cap production deploy

もし「え、うまくいかないんだけど、、、、、、、」ってなった時に試すこと

  • AWSコンソールから EC2再起動

  • nginx手動で再起動

  • Mysql手動で再起動

  • Unicornをkill
    してから もう一度自動デプロイコマンド実施
    これで上手くいくはず。あとはコードを見直してみてください。

    お疲れ様でした!