肉とビールとパンケーキ by @sotarok

少し大人になった「肉とご飯と甘いもの」

でも一応載せておくEthna×PEAR::Auth


通常の認証処理だけなら、これで充分です。アイドル時間を設定して、ログアウトさせるとかも可能。(一定時間操作をしない場合はセッション切れになる機能)

ちなみに、両者のバージョンは、

でござる。




まあ要求としては色々あると思うのですが、
あれですよね、ログインしてる人の情報を手に入れたいのは、なにもログインが必要な画面だけじゃないですよね。
例えば、トップページとかって、ログインしてなくても見れるけど、してたら右上に「こんにちは!○○さん!」みたいに表示させるとか。そんな要望にも応える仕様。
でも、後で自動ログイン機能とかつけたいから、PEAR::Authは使わない方向に決まりました。ま、このエントリは、無駄なことはいいからお手軽に認証してみたいという場合には役に立つかもしれません。


#余分なコメントは省いてますあしからず。


まずはアプリケーションの基底クラスのauth書き換え。

これが、「別に見るのにログインしてる必要はないけど、ログインしてるならログイン情報を取得したい」場合に。


{APPID}_ActionClass.php

<?php

require_once 'Auth/Auth.php';


class {APPID}_ActionClass extends Ethna_ActionClass
{
    /**
     *  @var    object  $loginauth  ログイン認証オブジェクト
     */
    var $loginauth;
    
    /**
     *  @var    object  $loginauth  ログインフラグ
     */
    var $is_login;
    

    /**
     *  アクション実行前の認証情報ゲット
     *
     *  @access public
     *  @return string  遷移名(nullなら正常終了, falseなら処理終了)
     */
    function authenticate()
    {

        if (!$this->session->isStart()) {
            $this->session->start(0) ;
        }
        
        $params = array(
            'dsn'           => $this->config->get('dsn'),
            'table'         => 'users',             // ユーザ情報のテーブル名
            'usernamecol'   => 'user_email',        // ユーザ名カラム名
            'passwordcol'   => 'user_password',     // パスワードカラム名
            'cryptType'     => 'sha1',              // 暗号化タイプ:md5よりsha1がいいよね?
            );
        
        // -- MDB 使う。PEARにインスコされてるやつなら別になんでもいい。DBでもいいけど別に・・・
        $this->loginauth =& new Auth('MDB', $params, '', false);
        // -- 1時間操作がなければログアウト
        $this->loginauth->setIdle(3600, true);
        
        $this->loginauth->start();
        
        // ログインしてれば、ログイン情報を取得しておく
        if($this->loginauth->getAuth() ){
             $this->is_login = true;
             $user['is_login'] = $this->is_login;
             $user['user_name'] = $this->loginauth->getUserName();
             $this->af->setApp('user', $user);
        }
        
        return null;
    }


    function prepare()
    {
        return parent::prepare();
    }

    function perform()
    {
        return parent::perform();
    }
}


で。認証が必要なページに配置するやつはこれ。Ethna使ってるのに、アクションクラスにフォーム値を設定しなくてもPEAR::Authの中で$_POSTを受け取ってるからログイン可能な点が非常にイラつく。笑


{APPID}_AuthActionClass.php*1

<?php

require_once 'Auth/Auth.php';


/**
 *  action実行クラス
 *
 *  @author     {$author}
 *  @package    Ibbb
 *  @access     public
 */
class {APPID}_AuthActionClass extends {APPID}_ActionClass
{
    
    /**
     *  アクション実行前の認証処理を行う
     *
     *  @access public
     *  @return string  遷移名(nullなら正常終了, falseなら処理終了)
     */
    function authenticate()
    {
        
        // -- セッションをスタートする
        if (!$this->session->isStart()) {
            $this->session->start(0) ;
        }
        
        
        $params = array(
            'dsn'           => $this->config->get('dsn'),
            'postUsername'  => 'user_email',        // ポストしてくるinputタグのname
            'postPassword'  => 'user_password',     // ポストしてくるinputタグのname
            'table'         => 'users',
            'usernamecol'   => 'user_email',
            'passwordcol'   => 'user_password',
            'cryptType'     => 'sha1',
            );
        
        $this->loginauth =& new Auth('MDB', $params, '', false);
        $this->loginauth->setIdle(2400, true);
        
        $this->loginauth->start();
        
        
        if( !$this->loginauth->getAuth() ){
            
            if ($this->loginauth->getStatus() == -1) {
                $this->ae->add('', '一定時間操作されなかったのでログアウトされました。操作を続けるには再度ログインしてください');
            } else if ($this->loginauth->getStatus() == -3) {
                $this->ae->add('', 'IDまたはパスワードが違います');
            } else {
                $this->ae->add('', 'ログインしてください。');
            }
            
            return 'login';
        }
        
        $this->is_login = true;
        
        return null;
    }


    function prepare()
    {
        return parent::prepare();
    }

    function perform()
    {
        return parent::perform();
    }
}


そして、認証が必要なページでは(例えば、login_do)、

<?php
...

class {APPID}_Action_LoginDo extends {APPID}_AuthActionClass
{
    ...


みたいなあ〜。
認証の必要ないページで、ログイン情報を表示するために。{APPID}_ActionClass.phpで、ログイン情報をセットしてるので、テンプレートで

<{if $app.user.is_login}>
<div style="text-align:right;">ログイン中 :: <{$app.user.user_name}> | <a href="<{$config.url}>?action_logout=true">ログアウト</a></div>
<{else}>
<a href="<{$config.url}>?action_login=true">ログイン</a>
<{/if}>

てカンジにしとけば、ログインしてるときはログアウトメニュー、ログインしてないときはログインメニューを表示できる。



だいたいこんなとこかなあー。


あ、ちなみに書いておくと、EthnaはセッションID長いの作ってくれてるんだけど、PEAR::Authが、setAuth()(@line 810)で session_regenerate_id();しちゃってるから、短いセッションIDを生成しなおしてます。

あとなんか書くことあった気がするけど。忘れてたら後で書き足そう。

*1:Controllerでrequireする