この前書いたこの問題。
長いので以下ステージング環境認証問題と言うことにします。
(ステージング環境についてはこちら)
元エントリーにもコメントをいただき、大変参考になりました。僕の場合、3日考えて良い解決法が見つからない時は大抵1ヶ月かかっても見つからないのでブログに書いたり人に助けを求めたりします。(サーセン・・・)
今回もそれを実行したところid:dandasoにナイスアイデアを頂きました。(Thanks!)
皆様方におかれましては、
「そんなに悩むところか?」
感が否めないかもしれませんが、僕と同じく悩んだ方がいて、参考になったりすれば幸いです。
ステージング環境認証問題対応方法
一言で言うと、「クッキーの値で認証する」ということです。
fooというアプリがあるとして、まず、下記のようなBASIC認証をがかかった認証用クッキーを設定するプログラムを見えないとこに置きます。(PHPが便利でした)
<?php
$user = 'foo';
$pass = 'bar';
$realm = 'foo';
if ($_SERVER['PHP_AUTH_USER'] === $user and $_SERVER['PHP_AUTH_PW'] === $pass):
setcookie($realm, sha1($pass));
header('Location: /');
else:
header("WWW-Authenticate: Basic realm=\"{$realm}\"");
header("HTTP/1.0 401 Unauthorized");
?>
<html>
<head>
<title>Authentication</title>
</head>
<body>
<h1>Authentication</h1>
<p>正しいユーザー名とパスワードを入力してください。</p>
</body>
</html>
<?php endif ?>
本来、問題になっているアプリ「foo」に上記のアプリのAliasを張ります。(上記をfooのリポジトリに入れたくないので)
<VirtualHost *:80>
ServerName foo
Alias /auth /path_to/auth.php
...(snip)...
</VirtualHost>
fooのアプリのApplicationControllerでlogin_required(本来のBASIC認証)より先にcookieを見て認証します。(認証失敗したらさっきのPHPにリダイレクトする)
require 'digest/sha1'
class ApplicationController < ActionController::Base
...(snip)...
before_filter :cookie_auth_required if $STAGING
def cookie_auth_required
redirect_to "/auth" unless cookies["foo"] == Digest::SHA1.hexdigest("bar")
end
end
ステージング環境でのみこの認証を追加したいので、capの設定ファイルにステージング環境用フラグを追加するタスクを書きます。(フラグの書き方、もっとキモくない方法しりたいです・・・)
config/deploy/staging.rb:
namespace :deploy do
desc 'Added staging flag in production.rb'
task :before_restart do
run "echo '$STAGING = true' >> #{current_path}/config/environments/production.rb"
end
end
これで http://foo/auth というURLと foo / bar というID/PASSをお客さんに教えることでステージング環境を認証有りで確認してもらうことができました。
お客さんの手間と本来のアプリのリポジトリの影響を最小限にしたいがためにこんな形になりました。
ブラウザを閉じるまでの間、cookie内にパスワード(のハッシュ)があるので大事な認証に使うのは辞めた方がいいと思います。利便性とのトレードオフで今回の自分ような、見られても致命的な影響が無いものならいいかなと思いました。
Apacheの設定とかでcookieの値を見てはじければ、fooから認証コードが取れてもっとよさげです。そういうモジュールとか無いのかな?引き続き模索してみます。
参照