Ankündigung

Einklappen
Keine Ankündigung bisher.

Authorisized Klasse: Login und ACL

Einklappen

Neue Werbung 2019

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

  • Authorisized Klasse: Login und ACL

    Hallo

    Bin gerade an meinem Login und ACL am Designen. Nun frage ich mich ob ich Frontend Benutzer und Backend Benutzer komplett voneinader trennen soll oder nicht. Was ist der bessere und sichere Weg?

    Vor allem wenn man sich ins Backend eingeloggt hat sollte man natürlich sich im Frontend auch noch anmelden müssen. Und hier wird es tricky, da tappe ich noch im dunkeln.

    Hier wäre mal mein grober Versuch:

    Die AUTHORISZE Klasse:
    PHP-Code:
    abstract class Auth{

        protected 
    $_is_logged_in false;
        protected 
    $_logged_in_user_id 0;
        protected 
    $_user_task_objects;

        
    // Die abgeleitete Klasse zwingen, diese Methoden zu definieren
        
    abstract protected function init();
        abstract protected function 
    getUserData($loginname);
        abstract protected function 
    setUserLoggedInSession($user_id);
        
        
    // Gemeinsame Methode
        //check login and create session ???
        
    public function login($loginname$password) {
            global 
    $Services$Session//just for testing
            
    $login false;
            
            
    //check if loginname is username or email
            
            //validate post data
            
    $Validate $Services->get('validate'); //get Service valdiate
            
    $Validate->addRule($loginname'isAlphaNumeric');
            
    //$Validate->addRule($password, 'isPassword');
            //password encryption
            
            
    if ($Validate->isValid()){
                
    $user_check_query $this->getUserData($loginname);
                
                
    //checkUser: check if user exist and password is correct
                
    if (!empty($user_check_query)) {
                    
    //user exist
                    //print_r($user_check_query);
                    //echo 'username exist';
                    
    if ($user_check_query['password'] == $password) {
                        
                        
                        
    $login true;
                        
    $this->_is_logged_in true;
                        
    $this->_logged_in_user_id $user_check_query['id'];
                        
    $this->setUserLoggedInSession($this->_logged_in_user_id);
                        
                        
    $Session->regenerate();
                    }
                }
            
            } else {
                
    //validation has error
                
    $login false;
            }    

            
            return 
    $login;
        }


        public function 
    logout() {}
        
        public function 
    isLoggedIn() {
        
          if (
    $this->_is_logged_in == true) {
            return 
    true;
          }
          return 
    false;
        }
        
        public function 
    getLoggedInUserId() {
            return 
    $this->_logged_in_user_id;
        }


        public function 
    hasPermission($task$object) {
            if (
    $this->isLoggedIn()) {
                if (!empty(
    $this->_user_task_objects)) { //if no task = no permission at all!
                    
    foreach($this->_user_task_objects as $Task) {
                        if (
    $Task->getObject() == $object) {
                            if (
    $Task->getTask() == $task) {
                                return 
    true;
                            }
                        }
                    }
                }
            }
            return 
    false;
        }

        
        public function 
    setUserTaskObjects($user_task_objects) {
            
    $this->_user_task_objects $user_task_objects;
        }    
        
    }

    //class for frontend
    class AuthSite extends Auth{


        public function 
    init() {
            global 
    $Services$Session//just for testing
            
            //start the session
            
    $Session->start();
            
            if (isset(
    $_SESSION['site']['user_id']) && is_numeric($_SESSION['site']['user_id'])) {
                
    $this->_is_logged_in true;
                
                
    $this->_logged_in_user_id $_SESSION['site']['user_id'];
                echo 
    'SESSION EXIST<br>';
                
    //should we also regenerate session id on every new page???
                
    $Session->regenerate();
            }
        }
        
        
    //check login and create session ???
        
    protected function getUserData($loginname) {
            global 
    $Services$Session//just for testing
            
            //database table users
            
    $user_check_query $Services->get('database')->prepare('SELECT id, password, role_id FROM core_users WHERE username = :username');
            
    $user_check_query->execute(array(':username' => $loginname));
            
    $user_check_query $user_check_query->fetch();
            
            return 
    $user_check_query;
        }
        
        protected function 
    setUserLoggedInSession($user_id) {
            
    $_SESSION['site']['user_id'] = $user_id;
        }
        
    //end class 


    Dann um zu prüfen ob ein User eingelogt ist, wird dann auf jeder Seite eingebunden:
    PHP-Code:
    ###################  include on every site #########################
    //$Auth = $Services->get('Auth');
    $Auth = new AuthSite(); //later it comes from Services like above
    $Auth->init(); //checks if session user_id exist and if sets logged in to true
    //create user if logged in
    if ($Auth->isLoggedIn()) {
        echo 
    'session user_id exists<br>';
        
    $userFactory = new UserFactory();
        
    //creates User Object and role is assigned
        
    $User $userFactory->getUser($Auth->getLoggedInUserId()); //creates the user
        
    print_r($User);
        
    //create the user Role
        
    $UserRole = new UserRole(); 
        
    $UserRole->setRoleId($User->getRoleId());
        
        
    //create user task objects
        
    $userTaskFactory = new UserTaskFactory();
        
    $UserTasksObjects $userTaskFactory->getTasksObjects($User->getRoleId());
        
    //assign task object to $Auth
        
    $Auth->setUserTaskObjects($UserTasksObjects);
        
        
        
        
    //print_r($UserTasksObjects);
        
    } else { //just for testing
        //not logged in: redirect
        
    echo 'no session user_id exists<br>';
    }
    ################### End include on every site ######################### 
    Und zu guter letzt noch das Login script:
    PHP-Code:
    ###################  login script #########################
    $action = (isset($_POST['action']) ? $_POST['action'] : '');
    if(
    $action == 'login'){

        
    $login $Auth->login($_POST['username'], $_POST['password']); //true or false
        //login backend user
        //$login = $Auth->loginBackend($_POST['username'], $_POST['password']);
        
        
    if ($login) {
            
    //login successful redirect or whatever
            
    echo 'login succesful<br>';
            
        } else {
            
    //login failed, show error message
            
    echo 'login failed<br>';
        }
        
    }
    ###################  login script ######################### 

    und noch als Besipiel zum prüfen ob User Rechte hat:
    PHP-Code:
    ###################  testing user permission #########################    
    //check if User has permission to do a certain task
    if ($Auth->hasPermission('edit''article_seo')) {
        echo 
    'edit article seo allowed for this user';
    } else {
        echo 
    'edit article seo NOT allowed for this user';
    }
    ################### END testing user permission ######################### 

    Was meint Ihr ist das ein guter Weg? Irgendwie sagt mein Bauchgefühl das mit der Abrstakten Klasse ist nicht so gut.

  • #2
    Von Design seh ich hier wenig, du entwickelst schon lustig..

    User + Passwort beim Login Verifizieren
    -> Ursprungsort der Anmeldung ( Frontend / Backend ) erkennen
    -> Session FrontendUser- und/oder BackendUser-Instanz zuweisen ( serialisierbar ! )

    Beim Resourcenprüfen der ACL
    -> Session-UserInstanz öffnen und an die ACL übergeben
    -> Resource Erfragen

    Die ACL sollte dann Anhand des übergebenen Users prüfen ob er Zugriff hat oder nicht.. Das Frontend- / Backend trennst du Zugriffstechnisch doch durch die ACL, warum nicht dort auch entsprechend die Resourcen auftrennen.
    [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

    Kommentar


    • #3
      Hey Danke Dir vielmals trOy.

      Von Design seh ich hier wenig, du entwickelst schon lustig..
      Wie meinst Du denn das. Mache ich was grundlegend falsch?


      1.:User + Passwort beim Login Verifizieren
      Kommt noch bin ich noch am Knowhow sammeln in diversen Büchern und im Web.


      2.:Session FrontendUser- und/oder BackendUser-Instanz zuweisen ( serialisierbar ! )
      Da bin ich auch noch am rechechieren. Bin mir eben nicht sicher ob ich gleich das ganze User Object in die Session speichern soll oder nur die User_id?

      Warscheinlich ersteres. Denn wenn ich ja nur die User_id speichere müsste ich ja jedesmal eine DB anfrage machen um die restlichen Userdaten zu erhalten.

      Seriialisierbar? Werden ja automatisch serialisiert wie hier beschrieben ist:
      http://php.net/manual/en/oop4.serialization.php


      Die ACL sollte dann Anhand des übergebenen Users prüfen ob er Zugriff hat oder nicht.. Das Frontend- / Backend trennst du Zugriffstechnisch doch durch die ACL, warum nicht dort auch entsprechend die Resourcen auftrennen.
      Das macht wirklich Sinn. Mache ich eigentlich auch mit der Auth Klasse. Oder gehöhrt diese nicht zu einer ACL? Müsste ich dies nochmals trennen?

      Kommentar


      • #4
        Die Authentifizierung ist das eine und die Autorisierung (=ACL) das andere. Daher ein klares "Ja" zur Trennung.

        Kommentar


        • #5
          Hey danke Dir Trainmaster. Werde dann mal mein grobes Design überarbeiten mit den nützlichen Tips von Euch.

          Kommentar


          • #6
            So ich habe mal probiert dies so zu trennen: Schnell fällt aber auf das man auch schon in der Authentifizierung Frontend von Backend Usern unterscheiden muss.

            Hier mal neu umgeschrieben:
            Die Klassen:
            PHP-Code:
            class Auth {
                
                public function 
            init() {
                    
            //prüft ob ein User schon angemeldet ist: wenn angemeldet Status setzen als logged_in
                    //wenn Session existiert prüfen mit der Datenbank
                
            }
                
                public function 
            login($loginname$password) {
                    
            //Loginname und Passwort prüfen
                    //Frontend/Backend Erkennung des Users
                    //falls gültig: Session setzen und in die DB speichern
                
            }
                public function 
            logout() {}
                public function 
            isLoggedIn() {}

            //end class


            class Acl {
                
                public function 
            setUserId($user_id) {}
                public function 
            hasPermission($task$object) {}

            //end class 
            Und jetzt wird ernst. Dies wird dann bei jedem Seitenaufruf eingebunden: z.B. in Boostrap
            PHP-Code:
            ###################  include on every site #########################
            $Auth = new Auth(); 
            $Auth->init(); //Prüfen ob User schon eingelogt ist

            $Acl = new Acl(); 

            //create user if logged in
            if ($Auth->isLoggedIn()) {
                
                
            //falls eingelogt user_id an Acl übergeben
                
            $Acl->setUserId($Auth->getLoggedInUserId());

                
            //User Objekt erstellen
                
            $userFactory = new UserFactory();
                
            $User $userFactory->getUser($Auth->getLoggedInUserId()); 
                
            //User Objekt an Service übergeben: DI
                
            $Services->addServiceArray('user'$User); 
                
                
            } else { 
            //just for testing
                //not logged in: do nothing
            }
            ################### End include on every site ######################### 
            Und dann nun zum prüfen:
            PHP-Code:
            ###################  testing user permission #########################    
            //check if User has permission to do a certain task
            if ($Acl->hasPermission('edit''article_seo')) {
                echo 
            'edit article seo allowed for this user';
            } else {
                echo 
            'edit article seo NOT allowed for this user';
            }
            ################### END testing user permission ######################### 

            Was meint ihr dazu? Wäre dieser Lösungsansatz besser? Danke im voraus.

            Kommentar


            • #7
              es ist noch nicht ganz getrennt

              PHP-Code:
                  $Acl->setUserId($Auth->getLoggedInUserId()); 
              autorisierung kann auch bei gast usern passieren(zb dürfen gäste hier im Forum beiträge lesen). von daher würde ich garnicht prüfen ob user einloggt ist, sondern ledeglich seine rollen abfragen.

              schau dir am besten Zend ACL an
              http://framework.zend.com/manual/1.1....refining.html
              apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

              Kommentar


              • #8
                Hallo,

                um die beiden Sachen zu trennen musst du sie zu erst einmal komplett getrennt betrachten und dir im Kopf den Ablauf schlider, was kommt wann.

                Zuerst kommt doch die Authentifizierung, wenn dieser Vorgang startet kann und sollte überhaupt noch nichts bekannt sein, was der sich zu athentizierende darf oder nicht darf, ob er fürs backend zuständig ist oder nicht. Ein Benutzer kann doch für beides Rechte haben oder?

                Also erst mal gehört deine Authentifizierung umgesetzt, in der denkst du noch gar nicht an irgendwelche Rechtevergaben oder Backend oder Frontend. Setze deine Auth flexibel um, was bedeutet das sie mit einer DB funktioniert, genauso aber auch mit einer xml, txt, csv oder anderen Formaten.

                Dann wenn der User authentifiziert ist und erst dann, beginnt der Prozess die ACL zusammenzustellen, da drin steht dann was er wo darf oder auch nicht. Die ACL kannst du am besten in einer DB abspeichern und verwalten, es gehen natürlich auch andere Formate.

                Denke bei der ACL aber nicht an Vererbung, den Fehler habe ich auch mal gemacht.

                Gruß der Litter
                Aus dem Dynamo Lande kommen wir. Trinken immer reichlich kühles Bier. Und dann sind wir alle voll, die Stimmung ist so toll. Aus dem Dynamo Lande kommen wir.
                [URL]http://www.lit-web.de[/URL]

                Kommentar


                • #9
                  Zitat von litterauspirna Beitrag anzeigen

                  Dann wenn der User authentifiziert ist und erst dann, beginnt der Prozess die ACL zusammenzustellen, da drin steht dann was er wo darf oder auch nicht.
                  PHP-Code:
                  $acl = new Zend_Acl();
                   
                  $acl->addRole(new Zend_Acl_Role('guest'))
                      ->
                  addRole(new Zend_Acl_Role('member'))
                      ->
                  addRole(new Zend_Acl_Role('admin'));
                   
                  $parents = array('guest''member''admin');
                  $acl->addRole(new Zend_Acl_Role('someUser'), $parents); 
                  rolle guest braucht aber keine authentizierung jedoch hat die einige berechtigungen
                  apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                  Kommentar


                  • #10
                    Hey super Danke Euch beiden vielmals für die tolle Erläuterungen.

                    Ich denke ich mache folgendes:

                    Wenn die Seite aufgeruft wird passiert folgendes:

                    Authentifizierung:
                    überprüft ob nur Gast oder eingeloggt.

                    Session:
                    wird angelegt. Für jederman, gespeichert in der DB.

                    User Objekt:
                    wird erstellt auch wenn man nur Gast ist. Jederman.


                    ACL:
                    Jetzt kommen die Rechte ins Spiel

                    Kommentar


                    • #11
                      ich würde sagen, du erstellst dir eine bootstrap.php die am anfang geladen wird, welche deine anwendung inizialisiert. anhand einer Konfiguration , erstellst du Rollen, Resourcen und welche Rolle hat zugriff auf Resource.

                      Du vergibst am anfang jedem user die Gast Rolle, nach dem login kriegt der user zb User Rolle dazu. beim aufrufen deines Controllers oder Action prüfst du ob die Rolle zugriff auf die Resource hat unabhängig davon ob ein user eingeloggt ist oder nicht.

                      Die Resourcen sind ledeglich Objekte mit mehtoden und namen. Ich habe zb als namen für Resource Controller.Action genommen, die konfiguration sa dann etwa so aus:

                      PHP-Code:
                      //acl_config
                      return array(
                      'Gues'=>array(
                      'allow'=>array(
                      'blog.view',
                      'pages.*'
                      ),
                      deny => NULL // 
                      ),
                      'User'=>array(
                      'allow'=>array(
                      'blog.reply',
                      )
                      ),
                      'deny'=>NULL,//
                      'parent'=>array('Guest')// erbe von gast die allow und deny regeln

                      apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                      Kommentar


                      • #12
                        Code:
                        class AclContainer
                           extends Pimple
                        {
                        
                           public function __construct()
                           {
                              $that = $this;
                        
                              $this['rules'] = Symfony\Component\Yaml\Yaml::parse('config/rules.yml');
                        
                              $this['acl'] = $this->share(function() use ( $that ) {
                                 return new Acl($that['rules']);
                              });
                           }
                        
                           public function getAclObject()
                           {
                              return $this['acl'];
                           }
                        
                        }
                        Code:
                        ---
                        Guest:
                        
                           Allow: [ "blog.view", "pages.*" ]
                        
                           Deny: []
                        
                        User:
                        
                           Allow: [ "blog.reply" ]
                        
                           Deny: []
                        
                           Parent: [ "Guest" ] # Erbe von Gast ;(
                        Code:
                        {
                           "require": {
                              "Symfony/Yaml":"dev-master",
                              "Pimple/Pimple":"dev-master"
                           }
                        }
                        Luki-Luki!

                        *rumpfeif*
                        [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

                        Kommentar


                        • #13
                          Zitat von BlackScorp Beitrag anzeigen
                          rolle guest braucht aber keine authentizierung jedoch hat die einige berechtigungen
                          Stimmt, hast du vollkommen recht. Ich mache das bei mir so das immer geprüft wird ob eine Authentifizierung vorliegt, wenn nicht hole ich alles an Rechten aus der DB was zur Rolle guest gehört. Ist der Benutzer eingeloggt dann wird alles geholt was mit ihm in Verbindung steht.

                          Ich regel das in meiner DB mit folgenden Tabellen.

                          user_roles
                          users
                          users_acl
                          user_to_acl
                          Aus dem Dynamo Lande kommen wir. Trinken immer reichlich kühles Bier. Und dann sind wir alle voll, die Stimmung ist so toll. Aus dem Dynamo Lande kommen wir.
                          [URL]http://www.lit-web.de[/URL]

                          Kommentar


                          • #14
                            Hey danke Euch für den tollen Support und den tollen Codesnippet.

                            ich würde sagen, du erstellst dir eine bootstrap.php die am anfang geladen wird, welche deine anwendung inizialisiert
                            Jep ich habe schon eine bootstrap in welcher jedoch die Apllikations Klasse geladen wird. In dieser wird dann alles Konfiguriert (wie. z.B. Sprachen, Konfigurationen, Sessions, Cache etc.)

                            Zusätzlich habe ich mir das so vorgestellt das man im Backend zusätzliche Rollen anlegen kann und defineren was diese Rolle darf. Aber das kriege ich dann auch noch hin.

                            Als Besipiel zu einer selbst definierten Rolle im Backend:
                            wenn man die Kompente Onlineshop aktiviert hat oder installiert, möchte man z.B. eine bestimme Rolle machen welche weniger für ein Produkt bezahlen müssen. Stichwort Reseller.

                            Das wäre dann so mein zusätzliches Ziel.

                            Dank Eurer Hilfe ist mir einiges klarer geworden Danke viel vielmal.

                            Kommentar


                            • #15
                              Zitat von strub Beitrag anzeigen
                              Als Besipiel zu einer selbst definierten Rolle im Backend:
                              wenn man die Kompente Onlineshop aktiviert hat oder installiert, möchte man z.B. eine bestimme Rolle machen welche weniger für ein Produkt bezahlen müssen. Stichwort Reseller.

                              Moment, stopp.

                              Du verwechselst hier grad in dem Fall Benutzerrollen und Gruppeneinstellungen.

                              Das heist das es keine Rolle ist wenn jemand weniger bezahlen kann. Wenn du nun sagen willst du hast drei verschiedene Benutzergruppen die weniger bezahlen, dann legst du die Gruppen an und ordnest den Gruppen User zu. Anhand der Gruppenzugehörigkeit legst du dann die Zahlungsberechnung fest. Nicht anhand einer Rolle, denn es kann Benutzer mit unterschiedlichen Rollen geben die aber einer gemeinsamen Kundengruppe angehören.
                              Aus dem Dynamo Lande kommen wir. Trinken immer reichlich kühles Bier. Und dann sind wir alle voll, die Stimmung ist so toll. Aus dem Dynamo Lande kommen wir.
                              [URL]http://www.lit-web.de[/URL]

                              Kommentar

                              Lädt...
                              X