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でデコードしてあげればいいだけですもの。

の。