Duplicate DB sessions created upon Zend_Auth login

2019-01-29 03:41发布

问题:

I must be doing something wrong. I can't seem to find the answer to my problem anywhere on the Web, and this generally means that the solution is so simple that no one needs an answer on it.

I am using a database to store my session. I set it up in my bootstrap like this:


    protected function _initDBSessions(){
        $resource = $this->getPluginResource('db'); //from config.ini?
        $db = $resource->getOptions(); 
        $adapter = new Zend_Db_Adapter_Pdo_Mysql($db["params"]);

        Zend_Db_Table_Abstract::setDefaultAdapter($adapter); 
        $config = array('name'=>'sessions','primary'=>'id','modifiedColumn'=>'modified','dataColumn'=>'data','lifetimeColumn'=>'lifetime');
        $options = array(   
                "strict"=>FALSE,
                "name"=>"eCubed",
                "use_cookies"=>FALSE
                );
        Zend_Session::setOptions($options);
        Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config));
    }

Next in my bootstrap is my plugin setup


    protected function _initPlugins(){
        Zend_Controller_Front::getInstance()->registerPlugin(new Acl_Acl());
    }

My Acl_Acl looks like this:


    class Acl_Acl extends Zend_Controller_Plugin_Abstract{

        public function preDispatch(Zend_controller_request_abstract $request){
            $acl = new Zend_Acl();

            //add roles
            $acl->addRole(new Zend_Acl_Role(Acl_Levels::$GUEST));
            $acl->addRole(new Zend_Acl_Role(Acl_Levels::$BASIC),Acl_Levels::$GUEST);
            $acl->addRole(new Zend_Acl_Role(Acl_Levels::$SHOP),Acl_Levels::$BASIC);
            $acl->addRole(new Zend_Acl_Role(Acl_Levels::$OFFICE),Acl_Levels::$SHOP);
            $acl->addRole(new Zend_Acl_Role(Acl_Levels::$EXECUTIVE),Acl_Levels::$OFFICE);
            $acl->addRole(new Zend_Acl_Role(Acl_Levels::$OWNER));
            $acl->addRole(new Zend_Acl_Role(Acl_Levels::$ADMIN),Acl_Levels::$OWNER);

            //add resources
            $acl->addResource("index");
            $acl->addResource("authenticate");
            $acl->addResource("error");
            $acl->addResource("employees");
            $acl->addResource("mold");
            $acl->addResource("search");
            $acl->addResource("shop");
            $acl->addResource("user");

            //access rules
            $acl->allow(null,array('index','error','authenticate')); //default resources


            //Guest member access
            $acl->allow(Acl_Levels::$GUEST,'mold',array('index','list-molds'));
            $acl->allow(Acl_Levels::$GUEST,'user',array('index','login','new-profile','my-profile'));

            //SHOP Member Access
            $acl->allow(Acl_Levels::$BASIC,'mold',array('get-mold','get-part','get-order','get-orders','get-parts','print-mold-labels','print-part-labels'));
            $acl->allow(Acl_Levels::$BASIC,'user',array('my-profile','profile'));

            //OFFICE Member Access

            //EXECUTIVE Member Access

            //OWNER Member Access

            //ADMIN Member Access

            //current user
            if(Zend_Auth::getInstance()->hasIdentity()){
                $level = Zend_Auth::getInstance()->getIdentity()->level;
            } else {
                $level = Acl_Levels::$GUEST;
            }

            $conroller = $request->controller;
            $action = $request->action;

            try {
                if(!$acl->isAllowed($level,$conroller,$action)){
                        $request->setControllerName('application-error');
                        $request->setActionName('not-authorized');
                }
            } catch (Exception $e){ 
                $request->setControllerName("application-error");
                $request->setActionName("error");

                $error = new Zend_Controller_Plugin_ErrorHandler();
                $error->type = Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER;
                $error->request = clone($request);
                $error->exception = $e;
                $request->setParam('error_handler',$error);
            }

        }   
    }

My Authentication Controller has the following action:


    public function loginAction(){
            $this->_helper->viewRenderer->setNoRender(TRUE);

            $loginForm = new Form_Login();
            $form = $loginForm->getLoginForm();
            $form->setAction("/authenticate/login");

            if($this->getRequest()->isPost()){
                if($form->isValid($_POST)){
                    $email = $form->getValue('email');
                    $pass = $form->getValue('password');

                    $authAdapter = $this->getAuthAdapter();
                    $authAdapter    ->setIdentity($email)
                                    ->setCredential($pass);
                    $result = Zend_Auth::getInstance()->authenticate($authAdapter);

                    if($result->isValid()){
                        $omit = array('password','timestamp','temp_password','active','created');
                        $identity = $authAdapter->getResultRowObject(NULL,$omit);

                        $authStorage = Zend_Auth::getInstance()->getStorage();
                        $authStorage->write($identity);

                        $nickname = $identity->nickname ? $identity->nickname : $identity->first_name;

                        $this->_helper->flashMessenger("Welcome back $nickname");

                        //Zend_Debug::dump($identity); exit;
                        $this->_redirect("/"); 

                    } else {
                        $this->_helper->flashMessenger("Unable to log you in.  Please try again");
                        $this->_redirect("/");
                    }
                }
            }
        }

My Database Structure: id : int modified: int lifetime: int data: text

All is well, right? Well, no...

First of all, a session is created every time someone who is not logged in refreshes or navigates to a page. This is acceptable, I guess...

The problem I have is that when I do finally log in, I can see that the database is storing the Zend_Auth identity and Flashmessenger perfectly, BUT ...

... IT IS ALSO CREATING A PHANTOM ROW IN THE DATABASE AS IF A NON-LOGGED IN USER IS NAVIGATING THE WEBSITE....

This makes authentication impossible because when the user is redirected the "Profile" page, for example, Zend is looking at the phantom session data which contains absolutely no data!

Below is the information stored in the Zend_Session database table as proof that stuff is stored:

Zend_Auth|a:1:{s:7:"storage";O:8:"stdClass":7:{s:2:"id";s:1:"2";s:5:"email";s:17:"wes@****.com";s:10:"first_name";s:6:"Wesley";s:9:"last_name";s:7:"*";s:5:"level";s:5:"basic";s:8:"nickname";s:3:"Wes";s:9:"lastlogin";s:19:"2011-07-14 19:30:36";}}__ZF|a:1:{s:14:"FlashMessenger";a:1:{s:4:"ENNH";i:1;}}FlashMessenger|a:1:{s:7:"default";a:1:{i:0;s:16:"Welcome back Wes";}}

This has been driving me nuts for 2 days now. I am under the impression that Zend_Session automatically uses only 1 session to store data, but these multiple entries are driving me mad!!

I hope I've given someone enough information to work off of.

回答1:

I figured out this problem...

As expected, the solution was a simple typo...

I don't know how to dramatically write the answer here, but the problem was...

My Database table, called "sessions" had the wrong data type.

The datatype for the id column was set to "int" (11)

instead it should be set to "char" (32)

DUH! I hope the 4 days I spent on this problem helps someone else out!