Posted at

Railsでサイト全体をbasic認証しつつ/pingだけ通したい

More than 5 years have passed since last update.

http_basic_authenticate_with してしまうとskip_before_actionの書き方がわからなかったので。


解決例

http_basic_authenticate_with realm: 'Staging', name: 'user', password: 'password'

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

before_action :site_http_basic_authenticate_with if Rails.env.production?

def site_http_basic_authenticate_with
authenticate_or_request_with_http_basic("Application") do |name, password|
name == ENV['MY_SITE_USERNAME'] && password == ENV['MY_SITE_SECRET']
end
end
end

app/controllers/home_controller.rb

class HomeController < ApplicationController

skip_before_action :site_http_basic_authenticate_with, only: [:ping]

def ping
render text: 'pong'
end
end


失敗例


skip_before_action http_basic_authenticate_with

http_basic_authenticate_with 使いつつ, 外したい側で skip_before_action :http_basic_authenticate_with

=> そんな名前のactionはない


skip_before_action authenticate_or_request_with_http_basic

http_basic_authenticate_with 使いつつ, その中身はbefore_actionでauthenticate_or_request_with_http_basic なので、外したい側で skip_before_action :authenticate_or_request_with_http_basic

=> これだとskip対象にならなかった。


skip_before_action { site_http_basic_authenticate_with }

これだともとのrails側実装にも近いし、仮に(?)basic認証複数になっても平気だし、ヨサげ。

class ApplicationController < ActionController::Base

before_action { site_http_basic_authenticate_with(name: ENV['MY_SITE_USERNAME'], password: ENV['MY_SITE_SECRET']) if Rails.env.production?

def site_http_basic_authenticate_with(options = {})
authenticate_or_request_with_http_basic(options['realm']||"Application") do |name, password|
name == options['name'] && password == options['password']
end
end
end

=> うまくskip指定が書けない。


see:

rails/rails#4-1-stable actionpack/lib/action_controller/metal/http_authentication.rb