CakePHP 2: Basic 認証

モデルを使わないのであれば、env 関数から PHP_AUTH_USER と PHP_AUTH_PW の値を直に取得できる。

class HelloController extends AppController
{
    public $autoRender = false;

    public function index() {

        if (null === env('PHP_AUTH_USER')) {
            echo 'キャンセルしました。';
            $this->response->statusCode('401');
            $this->response->header('WWW-Authenticate', 'Basic realm="My Realm"');
            $this->response->send();
            exit;
        } else {
            var_dump(
                env('PHP_AUTH_USER'), env('PHP_AUTH_PW')
            );
        }
    }

}

Basic 認証のカスタムクラスをつくってみよう。Controller/Component/Auth のもとに Basic2Authenticate.php を用意する。

class Basic2Authenticate {

	public function authenticate(CakeRequest $request, CakeResponse $response) {
		return true;
	}

    public function getUser($request) {
        if (env('PHP_AUTH_USER') === 'foo' && env('PHP_AUTH_PW') === 'bar') {
            return array('User' => array('id' => '1', 'username' => 'foo', 'password' => 'bar'));
        } else {
            return false;
        }
    }

	public function unauthenticated(CakeRequest $request, CakeResponse $response) {
		echo 'キャンセルしました。';
        $response->statusCode('401');
        $response->header('WWW-Authenticate: Basic realm="My Realm"');
        $response->send();
	}

}

コントローラーでつくった認証クラスを使ってみよう。

class HelloController extends AppController {

    public $autoRender = false;
    public $uses = array('User');

    public $components = array(
        'Auth' => array(
            'loginAction' => array(
            'controller' => 'hello',
            'action' => 'index',
        ),
            'authenticate' => array('Basic2' => array('userModel' => 'User'))
        )
    );

    public function index() {
        echo 'ログインしました。';
    }

}

今度はアカウントをデータベースに保存した上で認証してみよう。まずテーブルをつくる。

CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50),
    password VARCHAR(255)
);

データを保存する。

INSERT INTO users(username, password) VALUES('foo', '58fa67eb80ff64da2fbbc4c2142201ac36e6e0df');

パスワードハッシュは Security::hash を使って生成する。

$password = 'foo';
App::uses('Security', 'Utility');
echo Security::hash($password, null, true);

モデルをつくる。Model/User.php の内容は次のとおり。

class User extends AppModel {}

スキーマファイルを生成する。

Console/cake schema generate

コントローラーで試してみよう。

class HelloController extends AppController {

    public $autoRender = false;
    public $uses = array('User');

    public $components = array(
        'Auth' => array(
            'authenticate' => array('Basic' => array('userModel' => 'User')
            )
        )
    );

    public function index() {
        echo 'ログインしました。';
        var_dump($this->User->find('first'));
    }

}

Ubuntu: 古いバージョンの bison をインストールする

Ubuntu 14.04 の bison パッケージのバージョンが 3系 であるために phpbrew を使って PHP 5.6 をビルドできなかったので、linuxbrew を使って bison 2.7 をインストールすることにした。

brew tap homebrew/versions
brew install homebrew/versions/bison27

homebrew をセットアップするには

ruby -e "$(wget -O- https://raw.github.com/Homebrew/linuxbrew/go/install)"
export PATH="$HOME/.linuxbrew/bin:$PATH"
export LD_LIBRARY_PATH="$HOME/.linuxbrew/lib:$LD_LIBRARY_PATH"

Mac OSX: Apache 2.4 で Lua を利用する

djl/apache2/apache24 のリポジトリを利用させてもらう。

brew tap djl/homebrew-apache2
brew install djl/apache2/apache24 --with-lua

/usr/local/etc/apache2/httpd.conf を編集して次のコードを追加する。

<Files *.lua>
    SetHandler lua-script
</Files>

Apache を再起動させたら、次のようなスクリプトをつくって http://localhost/test.lua にアクセスしてみよう。mod_lua のマニュアルによると、まだ実験的な段階なのでローカルで遊ぶ程度に留めておいたほうがよいだろう。

function handle(r)
    r.content_type = "text/html"
    r:puts("Hello world!")
    return apache2.OK
end

CakePHP 2: テーブルを使わないモデル

モデルの useTable プロパティに false を指定すればよい。

class User extends AppModel {

    public $useTable = false;

    public $_schema = array(
        'id' => array(
            'type' => 'string',
            'length' => '10',
        ),
        'email' => array(
            'type' => 'string',
            'length' => 255
        )
    );

    public function find($type = 'first', $query = array()) {

        if ($type === 'first') {
            return array(
                'User' => array('id' => '0', 'email' => 'foo@example.com')
            );
        }

        return null;
    }
}

コントローラーから使ってみよう。

class TestController extends Controller {

    public $autoRender = false;
    public $uses = array('User');

    public function index() {
        var_dump(
            $this->User->find()
        );
    }
}

CakePHP 2: Blowfish ハッシュを生成する

Security コンポーネントを使う。内部の実装に使われる crypt 関数のマニュアルによると、PHP 5.3.7 以降であれば、ソルトの形式に $2y$ を使うことが推奨される。

class TestController extends Controller {

    public $autoRender = false;
    public $components = array('Security');

    public function index() {
        $password = 'mypassword';
        $salt = '$2y$14$wHhBmAgOMZEld9iJtV./aq';

        var_dump(
            Security::hash($password, 'blowfish', $salt)
        );
    }
}

SimplePasswordHasher や BlowfishPasswordHasher を使って Blowfish ハッシュを生成する場合、CakePHP 2.4 の時点ではソルトを指定できない。また check メソッドはタイミング攻撃の対策が施されていないので、password_hash、password_verify、hash_equals の利用を検討したほうがよいだろう。

ソルトを指定できるように BlowfishPasswordHasher を少し修正したクラスをつくってみよう。

// Lib/MyBlowfishPasswordHasher.php
App::uses('AbstractPasswordHasher', 'Controller/Component/Auth');
App::uses('Security', 'Utility');

class MyBlowfishPasswordHasher extends AbstractPasswordHasher {

    public function hash($password) {
        $salt = isset($this->_config['salt']) ? $this->_config['salt'] : false;
        return Security::hash($password, 'blowfish', $salt);
    }

    public function check($password, $hashedPassword) {

        if (function_exists('hash_equals')) {
            return hash_equals($hashedPassword, Security::hash($password, 'blowfish', $hashedPassword));
        } else {
            return $hashedPassword === Security::hash($password, 'blowfish', $hashedPassword);
        }

    }
}

つくったクラスを試してみよう。

App::uses('MyBlowfishPasswordHasher', 'Lib');

class TestController extends Controller {

    public $autoRender = false;
    public $components = array('Security');

    public function index() {
        $password = 'mypassword';
        $salt = '$2y$14$wHhBmAgOMZEld9iJtV./aq';

        $passwordHasher = new MyBlowfishPasswordHasher(array('salt' => $salt));
        $hash = $passwordHasher->hash($password);

        var_dump(
            '$2y$14$wHhBmAgOMZEld9iJtV./aeL0mBQ/9rIe3nO4WH1wlJSqpfPBP6e6O' === Security::hash($password, 'blowfish', $salt), 
            '$2y$14$wHhBmAgOMZEld9iJtV./aeL0mBQ/9rIe3nO4WH1wlJSqpfPBP6e6O' === $hash,
            true === $passwordHasher->check($password, $hash)
        );

    }
}
アーカイブ ランダム ホーム 次のページ ページ 1 / 371