We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Recently upgraded to php 7.2 from 7.0.32, and now I get an error

I have a base controller that "all" my controllers inherit from, and it handle login logic,setting of a key for API calls from the browser/views, and destroys the session and forwards them to a logout if it has expired. After hte upgrade, it's failing with an error now:

Forwarding inside a controller's initialize() method is forbidden 0 [internal function]: Phalcon\Dispatcher->forward(Array) 1 /var/www/html/dashboard/app/controllers/ControllerBase.php(104): Phalcon\Mvc\Dispatcher->forward(Array) 2 /var/www/html/dashboard/app/controllers/ControllerBase.php(67): ControllerBase->logout() 3 [internal function]: ControllerBase->initialize() 4 [internal function]: Phalcon\Dispatcher->dispatch() 5 /var/www/html/dashboard/public/index.php(45): Phalcon\Mvc\Application->handle() 6 {main}

Here is my BaseController:

<?php

use Phalcon\Mvc\Controller;
use Phalcon\Loader;

class ControllerBase extends Controller
{

    public function initialize()
    {
        //This line should be removed in production
        $this->enableDebug();

        /* Login logic */
        if ( $_POST['loginAttempt'] == "true" )
        {
            //Store the password the user supplied
            $this->session->set( 'username', $_POST['username'] );
            $password = $_POST['password'] ;

            //Check stored password against the LDAP server
            //Load the LdapClass
            $loader = new \Phalcon\Loader();
            $loader->registerClasses(
                array( "LdapClass" => "library/LdapClass.php" )
            );
            $loader->register();

            $ldapObj = new LdapClass();
            $ldapObj->username = $this->session->get('username');
            $ldapObj->password = $password;
            $ldapOk = $ldapObj->authenticateUser();

            if($ldapOk)
            {

                //Get userId from db, store in session
                $user = new UserModel();
                $userData = $user->getUserByUsername( $ldapObj->username );

                //Create API Token, store it in the DB and session
                $expiry = date_format(date_add(date_create('now'), new DateInterval('P1D')), 'Y-m-d H:i:s' );
                $token = $this->getToken();
                $user->setApiKey( $token, $expiry, $userData[0]->userId );                

                if ( isset($userData[0]->userId) )
                {
                    $this->session->set( 'userId', $userData[0]->userId );
                    $this->session->set( 'userData', $userData[0] );
                    $this->session->set( 'apiKey', $token );
                }
                else //Makes it blank, which causes the logic later below to kick them
                {
                    $this->session->set( 'userId', '' );
                }

                //Get user's groups from the LDAP server
                $this->session->set( 'userGroups', $ldapObj->memberOf() );
            }
        }

        //If no userId is present in the session (or session doesn't exist, so 
        //it's empty), kick 'em out 
        if ( empty( $this->session->get('userId') ) )
        {
            //Log them out/redirect to login page
            $this->logout();
        }
        /* End Login logic */

    }

    function makePre($vardump = NULL)
    {
        echo '<pre>';
        var_dump($vardump);
        echo '</pre>';
    }

    function enableDebug()
    {
        error_reporting(E_ALL);        
        $debug = new \Phalcon\Debug();
        $debug->listen();
    }

    /**
    * 
    * Log out current user
    */
    function logout()
    {
        //Destroy session if it exists
        if ( !empty( $this->session->get('userId') ) )
        {
            $this->session->destroy();
        }

        //Redirect to the login page
        return $this->dispatcher->forward(array( 
           'controller' => 'login', 'action' => 'index' 
        )); 
    }

    /*
     * API token code
     * 
     * Call getToken to get the API Token, then you need to put it into the db,
     * along with the time it should expire
     */
    function crypto_rand_secure($min, $max) {
        $range = $max - $min;
        if ($range < 0) return $min; // not so random...
        $log = log($range, 2);
        $bytes = (int) ($log / 8) + 1; // length in bytes
        $bits = (int) $log + 1; // length in bits
        $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
        do {

            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter; // discard irrelevant bits
        } while ($rnd >= $range);
        return $min + $rnd;
    }

    function getToken($length=32){
        $token = "";
        $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
        $codeAlphabet.= "0123456789";
        for($i=0;$i<$length;$i++){
            $token .= $codeAlphabet[$this->crypto_rand_secure(0,strlen($codeAlphabet))];
        }
        return $token;
    }

}

It's failing when it tries to kick me ot the logut()

Thanks!

why don't you use beforeExecuteRoute? all your code look like a plugin



6.6k

why don't you use beforeExecuteRoute? all your code look like a plugin

I don't know? I think my skills and understanding may not be up to the task. The goal of this controller is to provide the base for all other contorller (almost all of them anyway). Most importantly, to handle the login and forcibly logout any user that needs to be re-logged in.

Try changing the name of the initialize method to the beforeExecuteRoute method