CakePHP 3 – kurs wideo, część 3 – uwierzytelnianie

W tej części rozbudujemy naszą aplikację o mechanizm uwierzytelniania. Dzięki temu, wyłącznie zalogowani użytkownicy będą mogli dokonywać modyfikacji w bazie danych. Zastosowana metoda uwierzytelniania oparta jest na haszowaniu hasła. Dodatkowo we wpisie znajdziesz ciekawe dodatki, takie jak tworzenie pól wirtualnych czy autoryzowanie użytkowników i przyznawanie dostępu w zależności od jego roli w systemie.

ERRATA – na początku filmu, w tabeli users, pole id ma mieć wartość int(11) a nie int(1) – mówiłem 11, zaś omyłkowo wpisałem 1. Oznacza to, że po wpisaniu 10 użytkowników skończy się możliwość dodawania użytkowników. Za pomyłkę przepraszam.

Kody źródłowe dotyczące kursu wideo.

AppController.php

parent::initialize();
 
   $this->loadComponent('RequestHandler');
   $this->loadComponent('Flash');
 
   $this->loadComponent('Auth', [
     'loginRedirect' => ['controller' => 'Addresses', 'action' => 'index'],
     'authError' => 'Brak prawa dostępu!',
     'loginAction' => ['controller'=>'Users','action'=>'login'],
     'logoutRedirect' => ['controller' => 'Users','action' => 'login']
    ]);         
        //$this->loadComponent('Security');
        //$this->loadComponent('Csrf');
    }
 
 public function beforeFilter(Event $event){
 $this->Auth->allow(['login']);
 }

UsersController.php

public function login()
    {
        if ($this->request->is('post')) {
            $user = $this->Auth->identify();
            if ($user) {
                $this->Auth->setUser($user);
                return $this->redirect($this->Auth->redirectUrl());
            }
            $this->Flash->error(__('Błędna nazwa użytkownika lub hasło!'));
        }
    }
 
      public function logout()
    {
        return $this->redirect($this->Auth->logout());
        $this->Flash->error(__('Zostałeś wylogowany z systemu.'));
    }



User.pop – model

Na początku pliku: use Cake\Auth\DefaultPasswordHasher;
 
    protected function _setPassword($value)
    {
        $hasher = new DefaultPasswordHasher();
        return $hasher->hash($value);
    }

login.ctp

<?= $this->Form->create() ?>
<?= $this->Form->control('username', ['label'=>'Nazwa użytkownika', 'required'=>true, 'placeholder'=>'Wpisz nazwę użytkownika']) ?>
<?= $this->Form->control('password',['label'=>'Hasło', 'required'=>true, 'type'=>'password','placeholder'=>'Podaj hasło']) ?>
<?= $this->Form->submit('Zaloguj', ['class' => 'button']) ?>
<?= $this->Form->end() ?>

Dodatki extra
Jeżeli w tabeli users dodamy pole active typu unsigned tinyint(1) – CakePHP rozpoznaje ten typ jako boolean,  można zrealizować opcję możliwości zalogowania wyłącznie użytkownikom, którzy są aktywni (wartość pola active=1). Aby tego dokonać, należy zmodyfikować AppController jak poniżej:

$this->loadComponent('Auth', [
        'loginRedirect' => ['controller' => 'Addresses', 'action' => 'index'],
        'authError' => 'Brak prawa dostępu!',
        'loginAction' => ['controller'=>'Users','action'=>'login'],
        'logoutRedirect' => ['controller' => 'Titles','action' => 'index'],
        'authenticate' => [
           'Form' => [
             'userModel' => 'Users',
             'finder' => 'auth'
          ]],
           ]);

I w pliku Users.php (model) dodać funkcję:

public function findAuth(\Cake\ORM\Query $query, array $options)
     { 
   $query
      ->select(['id', 'username', 'password','fullname']) //Można wybrać tylko wymagane pola!
       ->andWhere(['Users.active' => 1]);
   return $query;
  }

Teraz będą mogli się zalogować jedynie użytkownicy, którzy są aktywni w systemie (active=1).

Kolejną fajną funkcjonalnością modeli w CakePHP jest możliwość tworzenia pól wirtualnych, opartych np. na innych polach. Na przykład,  jeżeli mamy pola: name i surname, to możemy wygenerować pole full_name, które będzie dostępne w kontrolerach i widokach. Aby wygenerować takie pole, należy w pliku encji User.php dodać metodę prywatną:

protected function _getFullName()
  {
      return $this->_properties['name'] . '  ' . $this->_properties['surname'];
  }

Po tym pole będzie dostępne pod nazwą full_name.

Autoryzacja, czyli kontrola dostępu 

Autoryzacja, obok  uwierzytelniania jest bardzo istotną kwestią, która potwierdza lub zaprzecza, czy zalogowany użytkownik jest uprawniony do uruchomienia danej akcji w kontrolerze.

  1. Należy dodać dodatkowe pole w tabeli users. Polem tym jest role typ varchar(20), w którym można wpisać dowolną rolkę użytkownika, np. admin, user, operator, etc.
  2. W AppController.php należy dodać w konfiguracji modułu Auth dodatkowy wiersz: ‚authorize’ => [‚Controller’].
  3. W każdym kontrolerze, należy dodać publiczną funkcję isAutorized($user), która będzie sprawdzać, czy dany użytkownik ma prawo do wykonywania akcji w kontrolerze. Jest to funkcja zapewniająca przydział dostępu zgodny z zasadą minimalnych uprawnień, więc dostęp do akcji w kontrolerze jest domyślnie zablokowany, zaś odblokowanie następuje wyłącznie dla wymienionych w tej funkcji akcji.
$this->loadComponent('Auth', [
        'authorize' => ['Controller'], // Włączenie autoryzacji w kontrolerach
        'loginRedirect' => ['controller' => 'Addresses', 'action' => 'index'],
        'loginAction' => ['controller'=>'Users','action'=>'login'],
        'logoutRedirect' => ['controller' => 'Users','action' => 'login'],
           ]);

Teraz, w każdym  kontrolerze dopisz funkcję isAuthorised, w której przyznaj prawa określonemu użytkownikowi prawa dostępu do określonych akcji:

 public function isAuthorized($user)
{
if (isset($user['role']) && ($user['role'] === 'admin')) {  // Dla użytkownika o roli admin
$allowedActions = ['edit','add','delete','view', 'index', 'logout']; // Pozwól na dostęp do tych akcji w tym kontrolerze
if(in_array($this->request->action, $allowedActions)) {
return true; }
}
if (isset($user['role']) && ($user['role'] === 'user')) { // Dla użytkownika o roli user
$allowedActions = ['view','index', 'logout'];  // Przyznaj dostęp do tych akcji w tym kontrolerze
if(in_array($this->request->action, $allowedActions)) {
return true; }
}
return false;
return parent::isAuthorized($user);
}

Od teraz uzyskujesz możliwość przyznawania użytkownikom praw dostępu do określonych akcji. Jak widać jest to bardzo proste do zrealizowania w CakePHP 3. Funkcję isAuthorised można także umieścić w AppController.php a wówczas będzie działać globalnie.



Pozostaje jeszcze kwestia edycji uprawnień. 

Po dodaniu pola role w tabeli users należy wygenerować na nowo kod poprzez bin\cake bake all users lub dodać w add.ctp i edit.ctp <?= $this->Form->input(‚role’, [‚label’ => ‚Rola w systemie’,’required’=>true]) ?>

Jednak domyślnie edycja pola role będzie się odbywać za pomocą zwykłego pola edit, do którego można pisać wszystko. Najlepiej, by rola była wybierana przy pomocy pola kombi.

Otwórz zatem plik src->Model->Table->Users.php i zamień (jeśli generowałeś przez bake) lub dopisz linię w funkcji validationDefault(Validator $validator)

$validator ->add('role', 'inList', [ 'rule' => ['inList', ['admin', 'user']], 'message' => 'Proszę wybrać poprawną rolę użytkownika!']);

Następnie w pliku szablonu (edit.ctp oraz sdd.ctp) dodać pole wyboru roli:

echo $this->Form->control('role', ['label'=>'Rola w systemie',
            'options' => ['admin'=>'Administrator systemu','user'=>'Użytkownik']]);

Od teraz przy edycji pola role, wyświetlane będzie pole typu kombi, z którego będzie można wybrać rolę w systemie. Oczywiście można dopisywać tyle ról, ile wymaga tego sytuacja.

 

1808total visits,1visits today

Dodaj do zakładek Link.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

1 + 9 =

This site uses Akismet to reduce spam. Learn how your comment data is processed.