ZendFrameworkでベーシック認証を試みる 自作編
( PHP )わけって、アプリ側(ZendFramework)でもベーシック認証できないかということで調べてみたらありました。
流れとしては、
1. 認証を行う対象のコントローラがリクエストされたら、認証用のリクエストを送信する 2. パスワードファイルは指定されたディレクトリから情報読み込み、そこから認証のチェックを行う 3. 認証できれば当該処理を終了させる 4. 認証できなければ、401にする
今回はプラグイン側で実行することにします。
/**
* My_Controller_Plugin_HttpBasicAuth
*
*/
class My_Controller_Plugin_HttpBasicAuth extends Zend_Controller_Plugin_Abstract
{
/**
* Basic認証
*
* @param Zend_Controller_Request_Abstract $request
*/
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
// init
$server = $this->getRequest()->getServer();
$htpasswdFile = "/home/html/public_html/.htpasswd";
// 処理系のアクションか?
if (file_exists($htpasswdFile) && is_file($htpasswdFile)) {
// init
$response = $this->getResponse();
$request = $this->getRequest();
// htpasswdから情報取得
$htpasswds = file($htpasswdFile);
// headerから情報取得
$authHeader = $request->getHeader('Authorization');
// 認証情報解析
$cryptPass = '';
$cryptUser = '';
if (preg_match('/Basic (.+)/', $authHeader, $matches)) {
$base64 = base64_decode($matches[1]);
$userInfo = explode(':', $base64);
$cryptUser = $userInfo[0];
// パスワード情報があるまでチェックする
foreach ($htpasswds as $line) {
if (empty($line)) {
continue;
}
$htpasswd = My_Util::trimAll(explode(':', $line));
$username = array_get($htpasswd, 0);
$password = array_get($htpasswd, 1);
// 送信されたパスワード
$cryptPass = crypt($userInfo[1], substr($password, 0, 2));
// 値は等しいければ終了
if ($password == $cryptPass && $username == $cryptUser ) {
return;
}
}
}
// 認証リクエスト送信
$response->setRawHeader('HTTP/1.1 401 Authorization Required');
$response->setRawHeader('WWW-Authenticate: Basic realm="My User"');
// 認証画面設定
$response->clearBody();
$request->setControllerName('error')
->setActionName('authrequired')
->setDispatched(false);
}
}
}
最後にapp.iniにプラグインを有効化して終了。
resources.frontController.plugins.HttpBasicAuth.class = "My_Controller_Plugin_HttpBasicAuth"
ベーシック認証の仕組みを理解してれば、容易くいけるものですね。
base64でデコードしてあげればいいだけですもの。
の。
