Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] generisches Auth Modul

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] generisches Auth Modul

    Hallo zusammen,


    ich habe vor knapp 2 Wochen ein Auth Modul auf Basis von Zend Framework erweitert, bin aber Designtechnisch noch nicht ganz zufrieden und wollte nachfragen, ob und was ich besser machen kann.

    Einstiegspunkt ist ein Plugin im Dispatchloop:

    PHP-Code:
    /**
         * checks if user has permisson to view page
         * - logs user in
         * - gets user role
         * - checks acl
         *
         * @see Bos_Auth
         * @see Zend_Auth
         * @see ErrorController
         * @param object Zend_Controller_Request_Abstract $request
         */
        
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
        {
            
    $action $request->getActionName();
            
    $controller $request->getControllerName();
            
    $module $request->getModuleName();
            if(
    $action === "logout" && $controller == "login") {
                
    Bos_Auth::logout($request);
            }
            if(
    $controller == "login" && $action == "login") {
                
    Bos_Auth::identify($request$module);
            }
            
    // Lade aktuelle Rolle aus der Identität (falls vorhanden)
            
    $role $this->_getRole($request);
            
    /**
             * !!! refresh, da evtl durch Auth geändert !!!
             */
            
    $module $request->getModuleName();
            
    $controller $request->getControllerName();
            
    $action $request->getActionName();
            
    // fallback
            
    if(empty($role)) {
                
    $role "guest";
            }
            
    // Hole ACL für Modul
            
    $acl Bos_Acl::getInstance($module);
            
    // Prüfe Rechte
            
    if (!$acl->isAllowed
                    
    (
                        
    $role,
                        
    $controller,
                        
    $action
                    
    )
                )
            {
                if(
    "development" == APPLICATION_ENVIRONMENT) {
                    
    Debug::dump("access denied"$request$role);
                }
                
    $request->setModuleName('default');
                
    $request->setControllerName('error');
                
    $request->setActionName('not-found');
            }
        } 
    Das Plugin wiederum ruft Bos_Auth auf, die über statische Methoden die Abhängigkeiten mappt. Auch hier die Frage, ob ihr das anders lösen würdet und wenn ja, wieso?
    PHP-Code:
    /**
     * @author Sebastian Sauer <info klammeraffe dynpages.de>
     * @copyright Sebastian Sauer 2009/2010
     * @package auth
     * @version 1.2
     */

    class Bos_Auth {

        
    /**
         * creates instances of auth module regarding to the module
         * encapsulate dependencies of Bos_Auth_Abstract
         * @param object Zend_Controller_Request_Abstract $request
         * @param $module [optional]
         * @return object Bos_Auth_Abstract
         */
        
    private static function _getAuthObject ($request$module "") {
            if(empty(
    $module)) {
                
    $module $request->getModuleName();
            }
            require_once 
    APPLICATION_PATH '/../library/Bos/Controller/Action/Helper/Notify.php';
            
    $notify = new Helper_Notify();
            switch (
    $module) {
                case 
    "customer" :
                case 
    "admin" :
                case 
    "default":
                    
    $class "Bos_Auth_" ucfirst ($module);
                    
    $auth = new $class ($request$notify);
                    break;
                default:
                    
    $auth = new Bos_Auth_Default($request$notify);
                    break;
            }
            return 
    $auth;
        }
        
    /**
         * user login
         * @param object Zend_Controller_Request_Abstract $request
         * @param $module [optional]
         */
        
    public static function identify(Zend_Controller_Request_Abstract $request$module "") {
            
    $auth self::_getAuthObject($request$module);
            
    $auth->identify();
        }
        
    /**
         * user logout
         * @param object Zend_Controller_Request_Abstract $request
         */
        
    public static function logout (Zend_Controller_Request_Abstract $request) {
            
    $auth self::_getAuthObject($request);
            
    $auth->logout();
        }
        
    /**
         * get user role by module
         * @param object Zend_Controller_Request_Abstract $request
         */
        
    public static function getRole (Zend_Controller_Request_Abstract $request) {
            
    $auth self::_getAuthObject($request);
            return 
    $auth->getRole();
        }

    Hier die abstrakte Parentclass des Auth Moduls, von der alle erben:

    PHP-Code:
    <?php

    /**
     * @author Sebastian Sauer <info klammeraffe dynpages.de>
     * @copyright Sebastian Sauer 2009/2010
     * @package auth
     * @version 1.3
     */

    abstract class Bos_Auth_Abstract {

        protected 
    $_request;

        
    /**
         * database table name
         * @var string
         */
        
    protected $_authTable "";

        
    /**
         * database table userfield field name
         * @var string
         */
        
    protected $_userField "";

        
    /**
         * database table password field name
         * @var string
         */
        
    protected $_passwordField "";

        
    /**
         * database table password salt field name
         * @var string
         */
        
    protected $_passwordSaltField "password_salt";

        
    /**
         * message templating namespace
         *
         * @var object Helper_Notify
         */

        
    protected $_notify;

        
    /**
         * cache auth adapter object for child classes
         * @var object Zend_Auth_Adapter_DbTable
         */
        
    private $_authAdapter null;

        const 
    storageModuleAppendix "AuthStorage";
        
    /**
         * login user
         */
        
    public function identify() {
            
    $request $this->_request;
            
    $post $request->getPost();
            
    $username $this->_filterUsername($post['username']);
            
    $password $post['password'];
            if(empty(
    $username) || empty($password)) {
                return;
            }
            
    $this->_doAuth($username$password);
        }

        abstract public function 
    getRole();

        
    /**
         * @param object Zend_Controller_Request_Abstract $request
         */
        
    public function __construct(
            
    Zend_Controller_Request_Abstract $request,
            
    Zend_Controller_Action_Helper_Abstract $notify
        
    ) {
            
    $this->_request $request;
            
    $auth Zend_Auth::getInstance();
            
    $module = (null === $request->getModuleName())
                ? 
    'default'
                
    $request->getModuleName();
            
    $namespace $module self::storageModuleAppendix;
            
    $auth->setStorage(new Zend_Auth_Storage_Session($namespace));
            
    $this->_notify $notify;
        }

        
    /**
         * getter for auth adapter object
         *
         * @return object Zend_Auth_Adapter_DbTable
         *
         * Initialisiere Authentifizierungsadapter
         * gesaltet! bootstrapping beachten
         * Führe Authentifizierung durch
         */
        
    protected function _getAuthAdapter () {
            if(
    is_null($this->_authAdapter)) {
                
    $authAdapter $this->_authAdapter = new Zend_Auth_Adapter_DbTable(
                    
    Zend_Registry::get('Zend_Db'),
                    
    $this->_authTable,
                    
    $this->_userField,
                    
    $this->_passwordField,
                    
    "MD5(
                        CONCAT('"
                            
    Zend_Registry::get('staticSalt')
                            . 
    "', password_salt, ?
                        )
                    )"
                
    );
            }
            return 
    $this->_authAdapter;
        }

        
    /**
         * filters Username
         * @see Zend_Filter_Alnum
         * @param string $username
         */
        
    protected function _filterUsername ($username) {
            
    $filter = new Zend_Filter_Alnum(true);
            return 
    $filter->filter($username);
        }

        public function 
    logout() {
            
    Zend_Auth::getInstance()->clearIdentity();
            unset(
    $_SESSION);
            
    // tweak the garbage collector
            
    $_SESSION null;
        }

        
    /**
         * check if username / password combination exists in database
         * sets storage data if auth is valid
         * @return bool
         */
        
    protected function _doAuth($username$password) {
            
    $authAdapter $this->_getAuthAdapter();
            
    // Übergebe Daten an Adapter
            
    $authAdapter->setIdentity($username);
            
    $authAdapter->setCredential($password);
            
    $result Zend_Auth::getInstance()->authenticate($authAdapter);
            if(
    $result->isValid()) {
                
    $authData $authAdapter->getResultRowObject();
                unset(
                  
    $authData->{$this->_passwordField},
                  
    $authData->{$this->_passwordSaltField}
                );
                
    Zend_Auth::getInstance()->getStorage()->write
                
    (
                    
    $authData
                
    );
            }
            return 
    $result->isValid();
        }
    }
    Problem ist dabei im Besonderen, dass $request->getControllerName() im default module "Controllernamen" enthält, die dabei alle auf einen Controller geroutet werden, um eine bestimmte Seite mit verschiedenen Inhalten anzeigen zu können. In dem Fall Bandprofile einer Community Page.

    Hier der Vollständigkeit halber noch das Default Module:

    PHP-Code:
    <?php

    /**
     * @author Sebastian Sauer <info klammeraffe dynpages.de>
     * @copyright Sebastian Sauer 2009/2010
     * @package auth
     * @version 1.3
     *
     * TODO:
     * - provide system notifications for banned / deactivated users
     * @see databaste table t_user_main.sStatus enum('DELETED','BANNED','PENDING','ACTIVE')
     *
     */

    class Bos_Auth_Default extends Bos_Auth_Abstract {

        
    /**
         * database table name
         * @var string
         */

        
    protected $_authTable "t_user_main";

        
    /**
         * database table userfield field name
         * @var string
         */

        
    protected $_userField "sUsername";

        
    /**
         * database table password field name
         * @var string
         */

        
    protected $_passwordField "sPassword";

        
    /**
         * @var object Zend_Session_Namespace
         */

        
    protected $_session null;

        
    /**
         * All controllers of default module
         * @see Bos_Config
         * @var array
         */

        
    private $_controllers null;

        
    /**
         * @return object instance of Zend_Session
         */

        
    protected function _getSessionNamespace ()
        {
            if(
    $this->_session === null) {
                
    $this->_session = new Zend_Session_Namespace("UserData");
            }
            return 
    $this->_session;
        }

        
    /**
         * just a bit tricky mapping:
         * this one is written to access bands direct by url/bandname
         * @see BandController index action
         * @return string controller name
         */

        
    private function _getController ()
        {
            
    $request $this->_request;
            
    $controller $request->getControllerName();
            if(
    is_null($this->_controllers)) {
                
    $this->_controllers Bos_Config::getInstance()->getControllers();
            }
            if(!
    in_array(strtolower($controller), $this->_controllers))
            {
                
    $request->setControllerName('band');
                
    $request->setActionName('index');
                return 
    'band';
            }
            return 
    $controller;
        }

        
    /**
         * @see Bos_BandControllers
         * @return void
         */

        
    private function _checkAuthForBandController ()
        {
            
    $session $this->_getSessionNamespace();
            
    $id_band intval($this->_request->getParam("id"));
            if(
    $id_band 0) {
                foreach(
    $session->bandset as $index => $band) {
                    if(
    $id_band === (int)$band->nId) {
                        return 
    $band->sRole;
                    }
                }
            } else if(!empty(
    $_SESSION["BandController"])) {
                foreach(
    $session->bandset as $index => $band) {
                    if(
    $_SESSION["BandController"]["BandId"] === (int)$band->nId) {
                        return 
    $band->sRole;
                    }
                }
            }
            return 
    "registered";
        }

        protected function 
    _valid() {}

        
    /**
         * provide a nice message if login was invalid - kill identity
         * @see Bos_SystemMessages
         */

        
    protected function _invalid () {
            
    $notify $this->_notify;
            
    $notify->prependHl "Anmeldung fehlgeschlagen.";
            
    $notify->attach = array(
                
    "Benutzer oder Passwort inkorrekt oder Benutzer existiert nicht.",
                
    "Bitte probiere es noch einmal."
            
    );
            
    Zend_Auth::getInstance()->clearIdentity();
        }

        
    /**
         * user registered - but still pending. Redirect him and remove his auth
         * TODO: give user ability to input his email address
         * @return void
         */

        
    private function _pending () {
            
    $notify $this->_notify;
            
    $request $this->_request;
            
    // messages
            
    $notify->prependHl "Bitte aktiviere deinen Account.";
            
    $notify->attach = array(
                
    "Solltest du <strong>keine</strong> Aktivierungs-Mail bekommen haben,kontaktiere bitte unser Team.",
                
    "Wir helfen dir dann so schnell wie möglich weiter."
            
    );
            
    // kill identity
            
    Zend_Auth::getInstance()->clearIdentity();
            
    // redirect
            
    $request->setModuleName('default');
            
    $request->setControllerName('register');
            
    $request->setActionName('activate');
        }

        
    /**
         * @return void
         */

        
    public function identify () {
            
    $request $this->_request;
            
    $post $request->getPost();
            
    $username $this->_filterUsername($post['username']);
            
    $password $post['password'];
            if(empty(
    $username) || empty($password)) {
                return 
    $this->_invalid();
            }
            
    $auth Zend_Auth::getInstance();
            if (
    false === $this->_doAuth($username$password)) {
                return 
    $this->_invalid();
            }
            
    $stat $auth->getStorage()->read()->sStatus;
            
    $session $this->_getSessionNamespace();
            if (
    $stat == "PENDING") {
                return 
    $this->_pending();
            }
            
    // Authentifizierung war erfolgreich
            
    $identity $auth->getIdentity();
            
    $users = new Users();
            
    /**
             * für acl band rolle speichern
             * alle Banddaten in Session persistent ablegen:
             */
            
    $session->bandset $users -> fetchBandProperties (
                
    $username
            
    );
            
    Zend_Registry::set('UserData'$session);
            
    $this->_valid();
        }

        
    /**
         * @return string
         */

        
    public function getRole() {
            
    $controller $this->_getController();
            
    $auth Zend_Auth::getInstance();
            if(
    false === $auth->hasIdentity()) {
                return 
    'guest';
            }
            
    User::getInstance()->writeLastSeen();
            if(
    "band" == $controller || "bandmedia" == $controller || "bandsettings" == $controller) {
                return 
    $this->_checkAuthForBandController();
            } else {
                return 
    "registered";
            }
        }
    }
    Kritik und Anregungen erwünscht
    I like cooking my family and my pets.
    Use commas. Don't be a psycho.
    [URL="http://jscouch.de"]Blog[/URL] - [URL="http://coverflowjs.github.io/coverflow/"]CoverflowJS[/URL]

  • #2
    PHP-Code:
    private function _pending () {
            
    $notify $this->_notify;
            
    $request $this->_request;
            
    // messages
            
    $notify->prependHl "Bitte aktiviere deinen Account.";
            
    $notify->attach = array(
                
    "Solltest du <strong>keine</strong> Aktivierungs-Mail bekommen haben,kontaktiere bitte unser Team.",
                
    "Wir helfen dir dann so schnell wie möglich weiter."
            
    );
            
    // kill identity
            
    Zend_Auth::getInstance()->clearIdentity();
            
    // redirect
            
    $request->setModuleName('default');
            
    $request->setControllerName('register');
            
    $request->setActionName('activate');
        } 
    Ich weiß ja nicht warum immer wieder html-Code in den Verarbeitungsteil eingebaut wird.

    Willst Du wirklich daß ein Webdesigner sich durch zig Scripte wühlen muß weil er das Wörtchen "keine"
    eben nicht "<strong>" haben will ?
    Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

    Kommentar


    • #3
      Was ist daran jetzt so speziell generisch?

      Kommentar


      • #4
        @ Koala: danke für den Input, das Teil ist "historisch gewachsen", kennt bestimmt jeder. Wobei sich das hoffentlich irgendwann durch gettext oder wie auch immer mal ändern wird.

        @ xm22: mir ist kein besserer threat titel eingefallen. Der Einwand bringt mich nur auch nicht weiter. Es ist eh schwer, sich öffentlicher Kritik zu stellen (mir jedenfalls fällt das schwer, eigenen Code zur Beurteilung zu posten, erst Recht hier im Softwaredesign-Forum). Auch wenn dein Post vielleicht eine Berechtigung hat, wäre mir Kritik am Stil, Anmerkungen zu Designfehlern, was verbesserungswürdig ist, .. lieber gewesen.

        Wenn ich das richtig verstanden habe, ist Bos_Auth::_getAuthObject() eine private factory, von dem her habe ich den thread dann generisch getauft. Lass mich gerne durch einen besseren Threadtitel korrigieren.
        I like cooking my family and my pets.
        Use commas. Don't be a psycho.
        [URL="http://jscouch.de"]Blog[/URL] - [URL="http://coverflowjs.github.io/coverflow/"]CoverflowJS[/URL]

        Kommentar


        • #5
          Auch wenn dein Post vielleicht eine Berechtigung hat, wäre mir Kritik am Stil, Anmerkungen zu Designfehlern, was verbesserungswürdig ist, .. lieber gewesen.
          warts ab - da wird sich sicher noch jemand melden der sich designtechnisch gut auskennt und auch die Integration in das ZF beurteilen kann.
          Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

          Kommentar


          • #6
            Hallo,

            in deinem Controller-Plugin ist mir aufgefallen, dass du den Login oder Logout an eine bestimmte Controller-Action koppelst. Das finde ich nicht so gut. Koppel Login und Logout doch einfach an einen Request-Parameter. So kannst du dich auf jeder Seite deiner Website ein oder ausloggen ohne die Seite zu verlassen.

            Man koennte deinen Code zwar so manipulieren, dass es immernoch geht (naemlich in dem ein anderes Action-Plugin die Request-Parameter module/controller/action bei einem entsprechenden Parameter neu setzt, so dass dein Action-Plugin es entsprechend deiner Abfrage ($action = "logout" ..) korrekt auswertet, aber das waere doch etwas unsinnig.

            Ausserdem finde ich es unschoen, dass du 2x die $module, $controller und $action Variablen rausschreibst.

            Ich habe das etwa so im dispatchLoopStartup():

            PHP-Code:
            <?php
            class LoginHandler extends Zend_Controller_Action_PluginHelper // hiess das so?
            public function dispatchLoopStartup() {
              if (
            $this->_isLogin()) {
                
            $this->_assureSsl(); // too late, make sure anyway
                
            $this->_doLogin();
              } elseif (
            $this->_isLogout()) {
                
            $this->_doLogout();
              }
            }

            protected function 
            _isLogin() {
              return 
            $this->_request->getPost("login"false);
            }

            protected function 
            _isLogout() {
              return 
            $this->_request->hasParam("logout");
            }

            protected function 
            _doLogin() {
              
            $params $this->_request->getPost();
              
            $form = new Anti_Form_Login($this->_db);
              if (
            $form->isValid($params)) {
                
            $session $this->_getSession();
                
            $session->userData $form->getUserData();
                
            Zend_Session::regenerateId();
                
            $this->_getView()->messageHelper()->addSuccessMessage("Login");
              } else {
                
            $form->populate($params);
                
            $this->_getView()->messageHelper()->addErrorMessages($form->getErrorMessages());
              }
            }

            protected function 
            _doLogout() {
              
            $this->_getSession()->unsetAll();
            }

            // plus Helfermethoden
            }
            So der Login ist jetzt getan und eigentlich auch sprechender Code. Jetzt kannst du in einem zweiten ActionHelper die ACL aufbereiten, je nach Login-Status.

            Grundsaetzlich ist mir das bei dir zuviel statischer Codeaufruf. Benutzt doch normale Instanzen und die Zend_Registry oder die FrontController-Parameter?! Irgendwo im Code hast du auch noch ein $_SESSION stehen, das sollte da auch nicht sein.

            Zu deiner Auth, finde ich relativ unflexibel mit customer, admin, default. Bei unserem aktuellen System haben wir Besucher, Gaeste, Benutzer, 3-4 erweiterte Benutzer und 2 Admintypen. Wie wuerdest du das bei dir aendern? Durch Codeaenderung?

            Deine ACL sollte die Rollen und Rechte aus der DB holen und entsprechend die Aufrufe, die fuer die aktuelle(n) Benutzerrechte nicht gelten auf deinen Error-Controller weiterleiten. So brauchst du nur in der DB oder einem Interface anhaken Objektbearbeiter darf Objekte bearbeiten und dann hat er die Rechte auch sofort, ohne Codeaenderung. Du legst ja wie ich das sehe codeseitig fest, was eine Rolle darf, oder? (Bos_Auth_*)

            Weitere Anmerkung:
            PHP-Code:
            // fallback
                    
            if(empty($role)) {
                        
            $role "guest";
                    } 
            Warum kann dein getRole() nicht garantieren, dass $role auch wirklich gesetzt ist?

            Deine Texte musst du dringend mal aus deinem Code raushalten. Zend bietet dir fast ueberall ein Zend_Translate an, notfalls holst du dir ueber den ViewRenderer den View und kannst den Zend_View_Helper_Translate ansprechen:
            PHP-Code:
            <?php
            $view
            ->translate("Das ist mein Text")
            ?>
            Ist auch nicht viel aufwendiger als vorher, dafuer kannst du mit dem Registrieren eines Zend_Translate-Adapters dann sofort alle Texte uebersetzen lassen. Ich wuerde dir raten, nirgends in deinem Quellcode deutsche Texte festzuschreiben. Benutz Platzhalter ("THIS_IS_MY_TEXT") oder direkt englisch.
            "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

            Kommentar


            • #7
              Und nochwas:

              benutz kein is_null(), === null ist viel schneller! Ausserdem benutz besser kein strtolower(), mb_strtolower() ist zukunftssicherer. Weiterhin mag ich dein $band->nId nicht. Das ist eine public-Property oder __get? Beides Murgs in meinen Augen. Warum? Entweder setzt du mit __set/__get eh nur direkt Werte in einem Array, dann kannst du gleich auf public properties setzen, ist zudem noch schneller, oder aber du verteilst wieder auf andere setter/getter-Methoden - warum dann nicht gleich diese setter/getter Methoden verwenden? Falls du eine generische Verarbeitung moechtest, benutz einen Codegenerator, dann ist dein Code auch schneller.

              PS: Wenn ich hier viel zu meckern finde, heisst das nicht, dass ich deinen Code schlecht finde Ist aber ja immer so...
              "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

              Kommentar


              • #8
                Hi,


                danke für die vielen Anmerkungen!
                PS: Wenn ich hier viel zu meckern finde, heisst das nicht, dass ich deinen Code schlecht finde Ist aber ja immer so...
                Darum geht es ja, ich wollte wissen, wie ihr es sauber findet/ was dazu lernen, nehm ich nicht mal im Ansatz krumm.

                in deinem Controller-Plugin ist mir aufgefallen, dass du den Login oder Logout an eine bestimmte Controller-Action koppelst. Das finde ich nicht so gut. Koppel Login und Logout doch einfach an einen Request-Parameter. So kannst du dich auf jeder Seite deiner Website ein oder ausloggen ohne die Seite zu verlassen.
                Ist beides, du kannt dich per request parameter ausloggen oder mit $request->setModulename/setControllerName/setActionName zu dem login/logout intern weiterleiten.

                edit: ich sehe gerade, bei dir ist das über Post Parameter gelöst, während ich das über die URL oder über controller forwarding löse. Muss ich mir nochmal anschauen.
                Ausserdem finde ich es unschoen, dass du 2x die $module, $controller und $action Variablen rausschreibst.
                Stimmt, kann den auth teil dahinter packen. Hatte nicht dran gedacht, dass der Login Controller immer erreichbar sein darf.

                Zu deiner Auth, finde ich relativ unflexibel mit customer, admin, default. Bei unserem aktuellen System haben wir Besucher, Gaeste, Benutzer, 3-4 erweiterte Benutzer und 2 Admintypen. Wie wuerdest du das bei dir aendern? Durch Codeaenderung?
                Nein, über die Ini des jeweiligen Moduls Sind jetzt 3 Module (customer, admin, default), wobei da sicher noch mehr hinzukommen. Der Fallback deswegen, da der Modulcode nicht zwangsweise von mir stammen muss. Jedes Modul hat beliebig viele eigene Benutzerrollen, wobei ich "guest" überall als Standardrolle "nicht eingeloggt" spezifiziert habe.

                Deine ACL sollte die Rollen und Rechte aus der DB holen und entsprechend die Aufrufe, die fuer die aktuelle(n) Benutzerrechte nicht gelten auf deinen Error-Controller weiterleiten. So brauchst du nur in der DB oder einem Interface anhaken Objektbearbeiter darf Objekte bearbeiten und dann hat er die Rechte auch sofort, ohne Codeaenderung. Du legst ja wie ich das sehe codeseitig fest, was eine Rolle darf, oder? (Bos_Auth_*)
                Ne, ist ja nur einloggen/ ausloggen/ Benutzerrolle holen fürs jeweilige Modul. (bzw + dementsprechend benachrichtigen). Der AuthAdapter lädt je nach verwendeter Datenbank + Tabelle/Feldnamen dann die Benutzerrolle.
                Das ist alles nur Auth, Bos_Acl erledigt das mit der von Auth gelieferten Benutzerrolle, wobei die ini nach dem Modulnamen benannt ist.

                Vom Grundaufbau her hatten wir beide das Plugin ursprünglich mal fast gleich mit änhlichen Methoden. Dein _doLogin wollte ich eben raushalten und je nach Modulnamen laden, da ich nicht für die Zukunft bestimmen wollte, wie ein anderer Programmierer den Auth machen will.

                Deine Texte musst du dringend mal aus deinem Code raushalten. Zend bietet dir fast ueberall ein Zend_Translate an, notfalls holst du dir ueber den ViewRenderer den View und kannst den Zend_View_Helper_Translate ansprechen
                Jo, da hast du definitiv Recht, sehe ich ja selbst so. Bos_Auth_Customer z.b. braucht auch schon kein notify mehr, von dem her muss ich da mal demnächst bei Gelegenheit die Abhängigkeiten überdenken.
                PHP-Code:
                class Bos_Auth_Customer extends Bos_Auth_Abstract {

                    
                /**
                     * database table name
                     * @var string
                     */

                    
                protected $_authTable "t_customers";

                    
                /**
                     * database table userfield field name
                     * @var string
                     */

                    
                protected $_userField "customernumber";

                    
                /**
                     * database table password field name
                     * @var string
                     */

                    
                protected $_passwordField "password";

                    public function 
                getRole () {
                        if(
                Zend_Auth::getInstance()->hasIdentity()) {
                            return 
                'customer';
                        }
                        return 
                'guest';
                    }


                benutz kein is_null(), === null ist viel schneller! Ausserdem benutz besser kein strtolower(), mb_strtolower() ist zukunftssicherer.
                geändert, danke

                Weiterhin mag ich dein $band->nId nicht. Das ist eine public-Property oder __get? Beides Murgs in meinen Augen. Warum? Entweder setzt du mit __set/__get eh nur direkt Werte in einem Array, dann kannst du gleich auf public properties setzen, ist zudem noch schneller, oder aber du verteilst wieder auf andere setter/getter-Methoden - warum dann nicht gleich diese setter/getter Methoden verwenden? Falls du eine generische Verarbeitung moechtest, benutz einen Codegenerator, dann ist dein Code auch schneller.
                Die Methode könnte man netterweise noch als Relikt aus vergangenen Tagen bezeichnen. Nach deinem Einwand hab ich mir angesehen, was da genau passiert und konnte den elseif part einfach rausnehmen. Sieht schon besser aus:
                PHP-Code:
                    private function _checkAuthForBandController ()
                    {
                        
                $session $this->_getSessionNamespace();
                        
                $id_band intval($this->_request->getParam("id"));
                        if(
                $id_band 0) {
                            foreach(
                $session->bandset as $index => $band) {
                                if(
                $id_band === (int)$band->nId) {
                                    return 
                $band->sRole;
                                }
                            }
                        }
                        return 
                "registered";
                    } 
                Ist als standardobjekt gespeichert, wobei die properties so aus der DB kommen. Jeder Benutzer kann max. in 3 Bands sein, daher wird die Schleife nie lang.
                Arrays wollte ich ursprünglich mal hernehmen. Hatte aber mMn. keine Vorteile, wenn ich die Bandid nicht als arraykey festlegen kann, da php die Eigenschaft hat, dann dementsprechend viele leere array-Elemente anzulegen (so dass das array unglaublich viel mehr Speicher braucht).
                Hat das Performance- Vorteile, wenn ich das in der session als array hinterlege und rekursiv durchlaufe? Wie löst du denn die Abhängigkeiten, die aus den Datenbankfeldnamen resultieren, auf?

                Danke und Grüße


                Basti
                I like cooking my family and my pets.
                Use commas. Don't be a psycho.
                [URL="http://jscouch.de"]Blog[/URL] - [URL="http://coverflowjs.github.io/coverflow/"]CoverflowJS[/URL]

                Kommentar


                • #9
                  Das ist zwar für das Thema hier mittlerweile obsolet, aber den Controller würde ich "Auth" oder so und nicht "Login" nennen.

                  Ich wusste gar nicht, dass man für verschiedene Module verschiedene Benutzergruppen benutzen kann..

                  Kommentar


                  • #10
                    Hab den Controller umbenannt, macht def. mehr Sinn. Hab das eben überarbeitet, danke für eure Inputs. Hier das überarbeitete Plugin. Den Fallback habe ich auch rausgenommen und durch eine Exception ersetzt.

                    PHP-Code:
                    <?php

                    /**
                     * @author Sebastian Sauer <info klammeraffe dynpages.de>
                     * @copyright Sebastian Sauer 2009/2010
                     * @package auth
                     * @version 1.2
                     */

                    class Bos_Plugin_Auth extends Zend_Controller_Plugin_Abstract {

                        protected 
                    $_request null;

                        
                    /**
                         * checks if user has permisson to view page
                         * - logs user in
                         * - gets user role
                         * - checks acl
                         *
                         * @see Bos_Auth
                         * @see Zend_Auth
                         * @see ErrorController
                         * @param object Zend_Controller_Request_Abstract $request
                         */
                        
                    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
                        {
                            
                    $auth Bos_Auth::create($request);
                            
                    $role $auth->getRole();
                            
                    $module $request->getModuleName();
                            
                    $controller $request->getControllerName();
                            
                    $action $request->getActionName();
                            if(empty(
                    $role) || !is_string($role)) {
                                throw new 
                    Bos_Auth_Exception ("no role appointed");
                            }
                            
                    // Hole ACL für Modul
                            
                    $acl Bos_Acl::getInstance($module);
                            
                    // Prüfe Rechte
                            
                    if (!$acl->isAllowed
                                    
                    (
                                        
                    $role,
                                        
                    $controller,
                                        
                    $action
                                    
                    )
                                )
                            {
                                if(
                    "development" == APPLICATION_ENVIRONMENT) {
                                    
                    Debug::dump("access denied"$request$role);
                                }
                                
                    $request->setModuleName('default');
                                
                    $request->setControllerName('error');
                                
                    $request->setActionName('not-found');
                            }
                        }
                    }
                    Hier noch Bos_Auth:
                    PHP-Code:
                    <?php

                    /**
                     * @author Sebastian Sauer <info klammeraffe dynpages.de>
                     * @copyright Sebastian Sauer 2009/2010
                     * @package auth
                     * @version 1.2
                     */

                    class Bos_Auth {

                        
                    /**
                         * creates instances of auth module regarding to the module
                         * encapsulate dependencies of Bos_Auth_Abstract
                         * @param object Zend_Controller_Request_Abstract $request
                         * @param $module [optional]
                         * @return object Bos_Auth_Abstract
                         */
                        
                    private static function _getAuthObject ($request) {
                            
                    $module $request->getModuleName();
                            require_once 
                    APPLICATION_PATH '/../library/Bos/Controller/Action/Helper/Notify.php';
                            
                    $notify = new Helper_Notify();
                            switch (
                    $module) {
                                case 
                    "customer" :
                                case 
                    "admin" :
                                case 
                    "default":
                                    
                    $class "Bos_Auth_" ucfirst ($module);
                                    
                    $auth = new $class ($request$notify);
                                    break;
                                default:
                                    
                    $auth = new Bos_Auth_Default($request$notify);
                                    break;
                            }
                            return 
                    $auth;
                        }
                        
                    /**
                         * @param object Zend_Controller_Request_Abstract $request
                         * @param $module [optional]
                         */
                        
                    public static function create(Zend_Controller_Request_Abstract $request) {
                            
                    $auth self::_getAuthObject($request);
                            
                    $action $request->getActionName();
                            switch (
                    $action) {
                                case 
                    "login":
                                    
                    $auth->identify();
                                    break;
                                case 
                    "logout":
                                    
                    $auth->logout();
                                    break;
                            }
                            return 
                    $auth;
                        }
                    }
                    Damit fallen auch die ganzen statischen Aufrufe weg. Damit bin ich soweit für mich zufrieden, falls euch jedoch noch was auffällt, immer raus damit
                    I like cooking my family and my pets.
                    Use commas. Don't be a psycho.
                    [URL="http://jscouch.de"]Blog[/URL] - [URL="http://coverflowjs.github.io/coverflow/"]CoverflowJS[/URL]

                    Kommentar

                    Lädt...
                    X