PHPerのためのMovable Type講座(その14)

| コメント(0) | トラックバック(0)

ログイン処理をPHPで実装してみよう、編。

PHPerのためのMovable Type

DynamicMTMLを使うと簡単に書けますが、今回はDynamicMTMLなしでも動くコードを紹介します。

ログインの処理フロー

  • ユーザー名とパスワードをポストする
  • ユーザー名から mt_author オブジェクトをロード
  • 渡されたパスワードを暗号化してデータベースの値と比較
  • 正しければ、クッキーをセット
  • mt_session レコードにセッション情報を保存

mt_session の session_kind は 'SI' とする。クッキー名は 'mt_commenter'。Session.pm のドキュメントにありますね。

=item SI

Active commenter sessions are held in SI sessions.

<?php
include( '/path/to/mt/php/mt.php' );
$mt = MT::get_instance( 1, '/path/to/mt/mt-config.cgi' );
if ( $_SERVER['REQUEST_METHOD'] != 'POST' ) {
    exit(); // POSTメソッドのみ受け付ける
}
if ( ( isset( $_REQUEST[ 'username' ] ) )
    && ( isset( $_REQUEST[ 'password' ] ) ) ) {
    $username = $_REQUEST[ 'username' ];
    $password = $_REQUEST[ 'password' ];
    $author = $mt->db()->fetch_author_by_name( $username );
    // もしくは、
    // $username = $mt->db()->escape( $username );
    // require_once( 'class.mt_author.php' );
    // $author = new Author;
    // $author->Load( "author_name='${username}'" );
    if ( isset( $author ) ) {
        if ( is_valid_password( $author, $password ) ) {
            $expires = 0;
            if ( isset( $_REQUEST[ 'remember' ] ) && $_REQUEST[ 'remember' ] ) {
                // パスワードを記憶する
                $expires = time() + 60 * 60 * 24 * 365;
            }
            if ( isset( $_REQUEST[ 'blog_id' ] ) ) {
                $blog_id = $_REQUEST[ 'blog_id' ];
                $blog = $mt->db()->fetch_blog( $blog_id );
            }
            if ( $blog ) {
                $site_url = $blog->site_url();
                $path = preg_replace( '!^https{0,1}://.{1,}?(/)!', '/', $site_url );
            } else {
                $path = $mt->config( 'CookiePath' );
            }
            $token = md5( uniqid( '', 1 ) ); // SessionIDを生成
            $user_cookie = 'mt_commenter';
            setcookie( $user_cookie, $token, $expires, $path );
            $session = $mt->db()->fetch_session( $token );
            $now = time();
            if ( empty( $session ) ) {
                require_once( 'class.mt_session.php' );
                $session = new Session;
                $session->session_id = $token;
                $session->session_kind = 'SI';
                $session->session_email = $author->email;
                $session->session_name = $username;
                $session->session_start = $now;
                $session->Save();
            } else {
                $session->session_start = $now;
                $session->Update();
            }
        }
    }
}

function is_valid_password ( $author, $password ) {
    // 正しいパスワードかどうかをチェックする
    $real_pass = $author->password;
    if ( strpos( $real_pass, '$6$' ) === 0 ) {
        // sha512
        // 「$6$暗号化文字列$暗号化されたパスワード」という形式になっている
        $search = preg_quote( '$6$', '/' );
        $real_pass = preg_replace( "/^$search/", '', $real_pass );
        list ( $salt, $real_pass ) = explode( '$', $real_pass );
        $digest = base64_encode( hash( 'sha512', $salt . $password, 1 ) );
        $password = rtrim( $digest, '==' );
    } elseif ( strpos( $real_pass, '{SHA}' ) === 0 ) {
        // sha1
        // 「{SHA}暗号化文字列$暗号化されたパスワード」という形式になっている
        $search = preg_quote( '{SHA}', '/' );
        $real_pass = preg_replace( "/^$search/", '', $real_pass );
        list ( $salt, $real_pass ) = explode( '$', $real_pass );
        $password = hash( 'sha1', $salt . $password );
    } else {
        // 古いMTの形式
        $password = crypt( $password, $real_pass );
    }
    if ( $real_pass === $password ) {
        return TRUE;
    }
    return FALSE;
}
?>

コードのコメントにも書いていますが、MTのパスワードは、sha512で暗号化されており、「$6$暗号化文字列$暗号化されたパスワード」という形式になっています。 ということで、ユーザーのパスワードを生成するロジックは以下。

function make_password ( $password, $hash = 'sha512' ) {
    $strs = 'abcdefghkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ012345679'; 
    $strs = preg_split( "//", $strs, 0, PREG_SPLIT_NO_EMPTY ); 
    $salt = '';
    for ( $i = 0 ; $i < 16; $i++ ) { 
        $salt .= $strs[ array_rand( $strs, 1 ) ]; 
    }
    if ( $hash == 'sha512' ) {
        $crypt_sha = '$6$' . $salt . '$' . base64_encode( hash( 'sha512', $salt . $password, 1 ) );
        $crypt_sha = rtrim( $crypt_sha, '==' );
    } else {
        $crypt_sha = '{SHA}' . $salt . '$' .  hash( 'sha1', $salt . $password );
    }
    return $crypt_sha;
}

せっかくなのでたまには課題

では、これでログイン処理ができたとして、以降のリクエストのログインチェック、ユーザー情報の取得とコンテクストへのセットはどのようにすればよいでしょうか?

トラックバック(0)

トラックバックURL: http://junnama.alfasado.net/cgi/mt/mt-tb.cgi/836

コメントする

Facebook

Twitter

このブログ記事について

このページは、Junnama Nodaが2014年5月22日 10:53に書いたブログ記事です。

ひとつ前のブログ記事は「大事なことなのでもう一度。MTを最新版にできない場合、とりあえずmt-upgrade.cgiを削除する。」です。

次のブログ記事は「Basic認証設定を管理画面から行える Movable Type プラグインを作った。」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 6.2.6