dq23171 2012-07-31 22:28
浏览 91

HTTP DIGEST AUTH问题

I have been using http digest auth for my API for a long time, seemingly it worked as I expected.

However it appears to error and prompt for re-auth three times. On the fourth it just logs the user for the email sent (as username) even though the passwords wrong

Im slightly confused as to why it doesnt keep re-authing until a valid password is sent.

    <?php


    class Model_Authentication_Init {


    const REALM = 'theaudienceauth';

    protected $user_id = NULL;
    protected $user_permissions = array();
    protected $user;
    protected $db;

    public static $instance;
    const ADMIN_PERMISSION_ID = 1;


    public function __construct() {
        $this->db = Zend_Registry::get('db');
    }


    public static function getInstance() {

        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }


    protected function extractData() {

        $realm = self::REALM;

        if (empty ( $_SERVER ['PHP_AUTH_DIGEST'] )) {
            header ( 'HTTP/1.1 401 Unauthorized' );
            header ( 'WWW-Authenticate: Digest realm="' . $realm . '",qop="auth",nonce="' . uniqid () . '",opaque="' . md5 ( $realm ) . '"' );
            exit ();
            die ( 'Text to send if user hits Cancel button' );
        }

        //be careful username on account isnt the same as username in the db also, later
        $data = http_digest_parse ( $_SERVER ['PHP_AUTH_DIGEST'] );
        return $data;
    }


    protected function validateData($data, $password) {

        $realm          = self::REALM;
        $A1             = md5 ( $data ['username'] . ':' . $realm . ':' . $password );
        $A2             = md5 ( $_SERVER ['REQUEST_METHOD'] . ':' . $data ['uri'] );
        $valid_response = md5 ( $A1 . ':' . $data ['nonce'] . ':' . $data ['nc'] . ':' . $data ['cnonce'] . ':' . $data ['qop'] . ':' . $A2 );

        if ($data ['response'] != $valid_response) {
            die ( 'Wrong Credentials!' );
        }
    }


    public function authData($data) {

        if (isset ($data ['username'])) {
            $account_q          = $this->db->query (" SELECT `id`, `encrypted_password` FROM `User` WHERE `email` = '".$data['username']."' AND `enabled` = 1 AND deleted = 0 ");
            $account            = $account_q->fetch ( PDO::FETCH_OBJ );
            $account_q->closeCursor();

            if (is_object ( $account )) {
                $password_fetched = decrypt_password ( $account->encrypted_password ); //@todo might need to decr.

                if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
                    define ( 'CONNECTED_ACCOUNT_ID', $account->id );
                }

                $_SESSION ['logged_in']             = 1;
                $_SESSION ['CONNECTED_ACCOUNT_ID']  = $account->id;
                $_SESSION ['email']                 = $data['username'];
                $user_permissions                   = Model_User_Permission::listing ( $account->id );
                $_SESSION['user_permissions']       = $user_permissions;
                $user_id                            = $account->id;
                $account                            = NULL;
            } else {
                die ( 'Could not auth with details passed: email: ' . $data ['username'] );
            }
        }

        $this->user_id              = $user_id;
        $this->user_permissions     = $user_permissions;
        return array($user_id, $user_permissions, $password_fetched);
    }


    /**
     * Main auth method
     * @throws Model_Exception_Application
     */
    public function auth() {

        $userId             = NULL;
        $user_permissions   = NULL;

        if (! isset ( $_SESSION ['logged_in'] ) || $_SESSION ['logged_in'] != 1) {

            $data = $this->extractData();
            list($userId, $user_permissions, $password_fetched) = $this->authData($data);

            // analyze the PHP_AUTH_DIGEST variable
            if (! ($data)) {
                throw new Model_Exception_Application ( 903 );
                die ( 'Wrong Credentials!' );
            }

            $this->validateData($data, $password_fetched);

        } else {
            if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
                define ( 'CONNECTED_ACCOUNT_ID', $_SESSION ['CONNECTED_ACCOUNT_ID'] );
            }
            $userId = $_SESSION ['CONNECTED_ACCOUNT_ID'];
            //if user permissions are not set to a session, set it
            $user_permissions = $_SESSION['user_permissions'] = Model_User_Permission::listing($userId);// isset($_SESSION['user_permissions']) && !empty($_SESSION['user_permissions']) ? $_SESSION['user_permissions'] : Model_User_Permission::listing($userId);
        }

        $this->user_id                  = $userId;
        $this->user = $_SESSION['user'] = Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => $userId)); //isset($_SESSION['user']) && !empty($_SESSION['user']) ? $_SESSION['user'] : Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => $userId));
        $this->user_permissions         = $user_permissions;
    }
}

The above is called by:

Model_Authentication_Init::getInstance($this->rest);

Edit: not sure what the cause was now, because it was a long time ago, but here we go:

<?php


class System_Authentication_Init {


    const REALM = 'auth';

    protected $user_permissions = array();
    protected $user;
    protected $db;

    public static $instance;
    const ADMIN_PERMISSION_ID = 1;


    public function __construct() {
        $this->db = Zend_Registry::get('db');
    }


    public static function getInstance() {

        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }


    protected function extractData() {

        $realm = self::REALM;

        if (empty ( $_SERVER ['PHP_AUTH_DIGEST'] )) {
            header ( 'HTTP/1.1 401 Unauthorized' );
            header ( 'WWW-Authenticate: Digest realm="' . $realm . '",qop="auth",nonce="' . uniqid () . '",opaque="' . md5 ( $realm ) . '"' );
            exit ();
            die ( 'Text to send if user hits Cancel button' );
        }

        //be careful username on account isnt the same as username in the db also, later
        $data = http_digest_parse ( $_SERVER ['PHP_AUTH_DIGEST'] );
        return $data;
    }


    protected function validateData($data, $password) {

        $realm          = self::REALM;
        $A1             = md5 ( $data ['username'] . ':' . $realm . ':' . $password );
        $A2             = md5 ( $_SERVER ['REQUEST_METHOD'] . ':' . $data ['uri'] );
        $valid_response = md5 ( $A1 . ':' . $data ['nonce'] . ':' . $data ['nc'] . ':' . $data ['cnonce'] . ':' . $data ['qop'] . ':' . $A2 );

        if ($data ['response'] != $valid_response) {
            session_destroy();
            session_unset();
            session_regenerate_id();
            die ( 'Wrong Credentials!' );
        }
    }


    public function authData($data) {

        if (isset ($data ['username'])) {
            $accountQuery       = $this->db->query (" SELECT `id`, `encrypted_password` FROM `User` WHERE `email` = '".$data['username']."' AND `enabled` = 1 AND deleted = 0 ");
            $account            = $accountQuery->fetch ( PDO::FETCH_OBJ );
            $accountQuery->closeCursor();

            if (is_object ( $account )) {
                $passwordReturned = decrypt_password ( $account->encrypted_password );

                if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
                    define ('CONNECTED_ACCOUNT_ID', $account->id);
                }

                $_SESSION ['logged_in']             = 1;
                $_SESSION ['CONNECTED_ACCOUNT_ID']  = $account->id;
                $_SESSION ['email']                 = $data['username'];
                $user_permissions                   = Model_User_Permission::listing ( $account->id );
                $_SESSION['user_permissions']       = $user_permissions;
                $account                            = NULL;
            } else {
                die ( 'Could not auth with details passed: email: ' . $data ['username'] );
            }
        }

        $this->user_permissions = $user_permissions;
        return array($user_permissions, $passwordReturned);
    }


    /**
     * Main auth method
     * @throws System_Exception_Application
     */
    public function authenticate() {

        $user_permissions   = NULL;

        if (! isset ( $_SESSION ['logged_in'] ) || $_SESSION ['logged_in'] != 1) {

            $data = $this->extractData();
            list($user_permissions, $passwordReturned) = $this->authData($data);

            // analyze the PHP_AUTH_DIGEST variable
            if (! ($data)) {
                throw new System_Exception_Application ( 903 );
                die ( 'Wrong Credentials!' );
            }

            $this->validateData($data, $passwordReturned);

        } else {
            if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
                define ( 'CONNECTED_ACCOUNT_ID', $_SESSION ['CONNECTED_ACCOUNT_ID'] );
            }
            //if user permissions are not set to a session, set it
            $user_permissions = $_SESSION['user_permissions'] = Model_User_Permission::listing(CONNECTED_ACCOUNT_ID);// isset($_SESSION['user_permissions']) && !empty($_SESSION['user_permissions']) ? $_SESSION['user_permissions'] : Model_User_Permission::listing($userId);
        }

        $this->user = $_SESSION['user'] = Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => CONNECTED_ACCOUNT_ID)); //isset($_SESSION['user']) && !empty($_SESSION['user']) ? $_SESSION['user'] : Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => $userId));
        $this->user_permissions         = $user_permissions;
    }


    public function isAdmin() {

        if (!$this->user_permissions || empty($this->user_permissions) ) {
            $this->authenticate();
        }   

        if ($this->user_permissions) {
            foreach ($this->user_permissions as $user_permission) {
                if (isset($user_permission->{'permission_id'}) && $user_permission->{'permission_id'} == self::ADMIN_PERMISSION_ID) {
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * returns user id
     * @return User id
     */
    public function getUserId() {
        return $this->user->id;
    }


    /* Added by aaron
     * returns the internal user object
     * */
    public function getUserObject() {
        Zend_Registry::set('user', $this->user);
        return $this->user;
    }


    /**
     * returns user permissions
     * @return _user_permissions User Permissions
     */
    public function getUserPermissions() {
        return $this->user_permissions;
    }


}
  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 微信会员卡等级和折扣规则
    • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
    • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
    • ¥15 gdf格式的脑电数据如何处理matlab
    • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
    • ¥100 监控抖音用户作品更新可以微信公众号提醒
    • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
    • ¥70 2048小游戏毕设项目
    • ¥20 mysql架构,按照姓名分表
    • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分