emlog整站代码分析 后台部分loginauth.php

作者:fly 发布于:2014-2-21 10:10 分类:Emlog

版权声明:本文系www.forwhat.cn原创 ,尊重作者劳动,转载请标明出处。本文转载自www.forwhat.cn谢谢

 

<?php
/**
 * 登录验证
 * @copyright (c) Emlog All Rights Reserved
 */

class LoginAuth{

    //以下三个常量分别是,用户名错误,密码错误,验证码错误。
    const LOGIN_ERROR_USER = -1;
    const LOGIN_ERROR_PASSWD = -2;
    const LOGIN_ERROR_AUTHCODE = -3;

    /**
     * 验证用户是否处于登录状态
     */
    public static function isLogin() {
        global $userData;
        $auth_cookie = '';
        if(isset($_COOKIE[AUTH_COOKIE_NAME])) {
            $auth_cookie = $_COOKIE[AUTH_COOKIE_NAME];
        } elseif (isset($_POST[AUTH_COOKIE_NAME])) {
            $auth_cookie = $_POST[AUTH_COOKIE_NAME];
        } else{
            return false;
        }

        if(($userData = self::validateAuthCookie($auth_cookie)) === false) {
            return false;
        }else{
            return true;
        }
    }

    /**
     * 验证密码/用户
     *
     * @param string $username
     * @param string $password
     * @param string $imgcode
     * @param string $logincode
     */
    public static function checkUser($username, $password, $imgcode, $logincode = false) {
        session_start();
        if (trim($username) == '' || trim($password) == '') {
	    //密码不能为空
            return false;
        } else {
  	    
            $sessionCode = isset($_SESSION['code']) ? $_SESSION['code'] : '';

	    //=是赋值  ==是比较值是否想等, ===要求两边类型与值都得想等才行。
            //看上去貌似有点乱,加一对括号就清楚了。
	    //现在看来。首次登录后台的时候, $logincode是默认值 $logincode是取得 Option::get('login_code') 
	    //应该是读取是否需要验证码。而当传入的值为不需要的时候,就确认一下,是否真的不需要。
            $logincode = (false === $logincode) ? Option::get('login_code') : $logincode;
            
	    //如果需要验证码。但是有没有传入严重呢干嘛,||后边是 或者验证码错误。就返回验证码错误了。
            if ($logincode == 'y' && (empty($imgcode) || $imgcode != $sessionCode)) {
                return self::LOGIN_ERROR_AUTHCODE;
            }
		
            //正在这里查询用户名是否存在。
            $userData = self::getUserDataByLogin($username);
            if (false === $userData) {
		//如果用户名不存在。就返回错误喽
                return self::LOGIN_ERROR_USER;
            }
	    //获取传入的密码。
            $hash = $userData['password'];
            //以下判断密码是否正确
            if (true === self::checkPassword($password, $hash)){
                return true;
            } else{
                return self::LOGIN_ERROR_PASSWD;
            }
        }
    }

    /**
     * 登录页面
     */
    public static function loginPage($errorCode = NULL) {
        Option::get('login_code') == 'y' ?
        $ckcode = "<span>验证码</span>
        <div class=\"val\"><input name=\"imgcode\" id=\"imgcode\" type=\"text\" />
        <img src=\"../include/lib/checkcode.php\" align=\"absmiddle\"></div>" :
        $ckcode = '';
        $error_msg = '';
        if ($errorCode) {
            switch ($errorCode) {
                case self::LOGIN_ERROR_AUTHCODE:
                    $error_msg = '验证错误,请重新输入';
                    break;
                case self::LOGIN_ERROR_USER:
                    $error_msg = '用户名错误,请重新输入';
                    break;
                case self::LOGIN_ERROR_PASSWD:
                    $error_msg = '密码错误,请重新输入';
                    break;
            }
        }
        require_once View::getView('login');
        View::output();
    }

    /**
     * 通过登录名查询管理员信息
     *
     * @param string $userLogin User's username
     * @return bool|object False on failure, User DB row object
     */
    public static function getUserDataByLogin($userLogin) {
        $DB = MySql::getInstance();
	//在这里,如果是先验证入参在执行数据库的实例化呢?尽管数据库实例是静态变量。显示文章甚么的,都需要用的到。
	//这里大部分情况下是不需要实际操作数据库的,而是直接返回对象。
	//不过个人还是感觉,先判断入参再执行数据库相关的操作,比较好。
        if (empty($userLogin)) {
            return false;
        }
        $userData = false;
        if (!$userData = $DB->once_fetch_array("SELECT * FROM ".DB_PREFIX."user WHERE username = '$userLogin'")) {
            return false;
        }
	//上边那一句。如果查询到了用户信息,才往下执行,否则就返回false了。
	//否则,就对读取到的信息处理一下,防止输出html信息。
        $userData['nickname'] = htmlspecialchars($userData['nickname']);
        $userData['username'] = htmlspecialchars($userData['username']);
        return $userData;
    }

    /**
     * 将明文密码和数据库加密后的密码进行验证
     *
     * @param string $password Plaintext user's password
     * @param string $hash Hash of the user's password to check against.
     * @return bool False, if the $password does not match the hashed password
     */
    public static function checkPassword($password, $hash) {
        global $em_hasher;//这里声明了全局变量。PasswordHash类在lib文件夹下。应该是对密码加密判断之类用的。
        if (empty($em_hasher)) {
            $em_hasher = new PasswordHash(8, true);
        }
        $check = $em_hasher->CheckPassword($password, $hash);
        return $check;
    }
    /**
     * 写用于登录验证cookie
     *
     * @param int $user_id User ID
     * @param bool $remember Whether to remember the user or not
     */
    public static function setAuthCookie($user_login, $ispersis = false) {
        if ($ispersis) {
	    //如果需要记住我,则设置一个超时时间。
	    //这一串销魂的数字,难道是。。。记住我一年?
            $expiration  = time() + 60 * 60 * 24 * 30 * 12;
        } else {
            $expiration = null;
        }
        $auth_cookie_name = AUTH_COOKIE_NAME;
	//下边开始生成cookie
        $auth_cookie = self::generateAuthCookie($user_login, $expiration);
        setcookie($auth_cookie_name, $auth_cookie, $expiration,'/');
    }

    /**
     * 生成登录验证cookie
     *
     * @param int $user_id user login
     * @param int $expiration Cookie expiration in seconds
     * @return string Authentication cookie contents
     */
    private static function generateAuthCookie($user_login, $expiration) {
        $key = self::emHash($user_login . '|' . $expiration);
        $hash = hash_hmac('md5', $user_login . '|' . $expiration, $key);

        $cookie = $user_login . '|' . $expiration . '|' . $hash;

        return $cookie;
    }

    /**
     * Get hash of given string.
     *
     * @param string $data Plain text to hash
     * @return string Hash of $data
     */
    private static function emHash($data) {
        $key = AUTH_KEY;
        return hash_hmac('md5', $data, $key);
    }

    /**
     * 验证cookie
     * Validates authentication cookie.
     *
     * @param string $cookie Optional. If used, will validate contents instead of cookie's
     * @return bool|int False if invalid cookie, User ID if valid.
     */
    private static function validateAuthCookie($cookie = '') {
        if (empty($cookie)) {
            return false;
        }

        $cookie_elements = explode('|', $cookie);
        if (count($cookie_elements) != 3) {
            return false;
        }

        list($username, $expiration, $hmac) = $cookie_elements;

        if (!empty($expiration) && $expiration < time()) {
            return false;
        }

        $key = self::emHash($username . '|' . $expiration);
        $hash = hash_hmac('md5', $username . '|' . $expiration, $key);

        if ($hmac != $hash) {
            return false;
        }

        $user = self::getUserDataByLogin($username);
        if (!$user) {
            return false;
        }
        return $user;
    }
}

 

发表评论:

 
Powered by emlog sitemap