PHPerのためのMovable Type講座(その14)
公開日 : 2014-05-22 10:53:03
ログイン処理をPHPで実装してみよう、編。
- PHPerのための Movable Type 講座(その1)
- PHPerのための Movable Type 講座(その2)
- PHPerのための Movable Type 講座(その3)
- PHPerのための Movable Type 講座(その4)
- PHPerのための Movable Type 講座(その5)
- PHPerのための Movable Type 講座(その6)
- PHPerのための Movable Type 講座(その7)
- PHPerのための Movable Type 講座(その8)
- PHPerのための Movable Type 講座(その9)
- PHPerのための Movable Type 講座(その10)
- PHPerのための Movable Type 講座(その11)
- PHPerのための Movable Type 講座(その12)
- PHPerのための Movable Type 講座(その13)
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::getinstance( 1, '/path/to/mt/mt-config.cgi' ); if ( $SERVER['REQUESTMETHOD'] != 'POST' ) { exit(); // POSTメソッドのみ受け付ける } if ( ( isset( $REQUEST[ 'username' ] ) ) && ( isset( $REQUEST[ 'password' ] ) ) ) { $username = $REQUEST[ 'username' ]; $password = $REQUEST[ 'password' ]; $author = $mt->db()->fetchauthorbyname( $username ); // もしくは、 // $username = $mt->db()->escape( $username ); // requireonce( 'class.mtauthor.php' ); // $author = new Author; // $author->Load( "authorname='${username}'" ); if ( isset( $author ) ) { if ( isvalidpassword( $author, $password ) ) { $expires = 0; if ( isset( $REQUEST[ 'remember' ] ) && $REQUEST[ 'remember' ] ) { // パスワードを記憶する $expires = time() + 60 * 60 * 24 * 365; } if ( isset( $REQUEST[ 'blogid' ] ) ) { $blogid = $REQUEST[ 'blogid' ]; $blog = $mt->db()->fetchblog( $blogid ); } if ( $blog ) { $siteurl = $blog->siteurl(); $path = pregreplace( '!^https{0,1}://.{1,}?(/)!', '/', $siteurl ); } else { $path = $mt->config( 'CookiePath' ); } $token = md5( uniqid( '', 1 ) ); // SessionIDを生成 $usercookie = 'mtcommenter'; setcookie( $usercookie, $token, $expires, $path ); $session = $mt->db()->fetchsession( $token ); $now = time(); if ( empty( $session ) ) { requireonce( 'class.mtsession.php' ); $session = new Session; $session->sessionid = $token; $session->sessionkind = 'SI'; $session->sessionemail = $author->email; $session->sessionname = $username; $session->sessionstart = $now; $session->Save(); } else { $session->sessionstart = $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;
}
せっかくなのでたまには課題
では、これでログイン処理ができたとして、以降のリクエストのログインチェック、ユーザー情報の取得とコンテクストへのセットはどのようにすればよいでしょうか?