Logowanie z Auth

Moduł Auth służy do autoryzacji (logowania) użytkowników w systemie. Postaram się w możliwie najkrótszy sposób wyjaśnić jak zacząć go używać. Aby z niego korzystać należy wykonać kilka czynności:

1. W /application/bootstrap.php włączyć moduły:
- Auth
- Database (jeśli chcemy przechowywać użytkowników w bazie)
- ORM (jeśli chcemy przechowywać użytkowników w bazie)
Jeśli tworzymy jakąś małą stronę, np. firmową, to wystarczy kilku użytkowników, więc możemy przechowywać ich w pliku.

2. Skonfigurować połączenie do bazy (skopiować z /modules/database/config/database.php do /application/config/ i ustawić dane do połączenia).

'hostname'   => 'localhost', //host na której znajduje się baza
'database'   => 'kohana', //nazwa bazy
'username'   => 'kohana', //użytkownik bazy
'password'   => 'kohana', //hasło

3. Wykorzystać plik /modules/orm/auth-schema-mysql.sql do stworzenia tabel, które wymaga Auth. Plik ten zawiera polecenia SQL, które należy wkleić w konsoli mysql lub phpmyadmin. Może się różnić pomiędzy wersjami, dlatego należy wykorzystywać go z wersji którą ściągnęliśmy, w KO 3.1.3.1 ma postać:

CREATE TABLE IF NOT EXISTS `roles` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `description` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `uniq_name` (`name`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `roles` (`id`, `name`, `description`) VALUES(1, 'login', 'Login privileges, granted after account confirmation');
INSERT INTO `roles` (`id`, `name`, `description`) VALUES(2, 'admin', 'Administrative user, has access to everything.');

CREATE TABLE IF NOT EXISTS `roles_users` (
  `user_id` int(10) UNSIGNED NOT NULL,
  `role_id` int(10) UNSIGNED NOT NULL,
  PRIMARY KEY  (`user_id`,`role_id`),
  KEY `fk_role_id` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` varchar(127) NOT NULL,
  `username` varchar(32) NOT NULL DEFAULT '',
  `password` varchar(64) NOT NULL,
  `logins` int(10) UNSIGNED NOT NULL DEFAULT '0',
  `last_login` int(10) UNSIGNED,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `uniq_username` (`username`),
  UNIQUE KEY `uniq_email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `user_tokens` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user_id` int(11) UNSIGNED NOT NULL,
  `user_agent` varchar(40) NOT NULL,
  `token` varchar(40) NOT NULL,
  `type` varchar(100) NOT NULL,
  `created` int(10) UNSIGNED NOT NULL,
  `expires` int(10) UNSIGNED NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `uniq_token` (`token`),
  KEY `fk_user_id` (`user_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

ALTER TABLE `roles_users`
  ADD CONSTRAINT `roles_users_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
  ADD CONSTRAINT `roles_users_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE;

ALTER TABLE `user_tokens`
  ADD CONSTRAINT `user_tokens_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;

W bazie mamy standardowo 2 role: login i admin. Aby użytkownik mógł się zalogować musi mieć rolę login, użytkownik, który będzie adminem, będzie musiał mieć obie role!
Przykład: Po rejestracji dodajemy użytkownika, ale nie dodajemy roli. Jeśli potwierdzi adres e-mail dodajemy mu rolę login. Użytkownik po potwierdzeniu może logować się i wykonywać czynności jakie zaprogramujemy dla tej roli. Jeśli dodalibyśmy rolę moderatora, np. mod, to użytkownikowi który ma być moderatorem trzeba dodać rolę mod (będzie miał role login i mod). Użytkownikowi, który ma być adminem dodajemy wszystkie role, które admin może wykonywać. Powinien więc mieć role login, mod i admin, tak aby mógł wykonywać czynności użytkowników zalogowanych, moderatorów i administratora.

4. Utworzyć plik konfiguracyjny Auth (/application/config/auth.php)

<?php defined('SYSPATH') or die('No direct access allowed.');

return array(

	'driver'       => 'ORM',
	'hash_method'  => 'sha256',
	'hash_key'     => hash_hmac('sha256', 'Wiadomosc do zahashowania', 'Tajny klucz'),
	'lifetime'     => 1209600,
	'session_key'  => 'auth_user',

	// Username/password combinations for the Auth File driver
	'users' => array(
		// 'admin' => '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918',
	),

);

Metoda hashowania służy do tego, aby w bazie nie przechowywać jawnych haseł. W przypadku przejęcia bazy uniemożliwia to bezpośrednie odczytanie haseł. Klucz hashowania (hsah_key) służy do tego, aby utrudnić atak brutal force. Jak jest tworzony hash_key nie koniecznie należy przechowywać w configu, jedynie wynik działania funkcji hash_hmac.
Jeśli chcemy przechowywać użytkowników w pliku jako driver podajemy ‚file’ i w tablicy niżej podajemy ich loginy i hasła zgodne z metodą (tu sha256).

5. Kontroler do obsługi Auth (np. /application/classes/controller/auth.php), rozszerza on kontroler Default (stworzony na tym blogu wcześniej).

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_Auth extends Controller_Default {

        public function action_login() {
            $this->template->content='login';
            $this->template->title=__('Login');
            if(isset($_POST['submit'])){
            $r = Auth::instance()->login($_POST['username'], $_POST['password']);
            }
            
            //if (Auth::instance()->logged_in()) {
            //    echo 'zalogowany';
            //    echo Auth::instance()->get_user();
            //    if (Auth::instance()->logged_in('admin')) {
            //    echo 'to jest admin';
            //   }
            //}
            // else {
            //    echo "User is not logged in";
            //}
        }
        public function action_logout() {
            Auth::instance()->logout();
            $this->request->redirect('/');
        }
        public function action_register() {
            $client = ORM::factory('user');
            $client->email = "admin@email.com";
            $client->username = "admin";
            $client->password = "admin";
            $client->save();

            //$role = ORM::factory('role','1');
            //$client->add('roles',$role);
            //$client->save();
        }
}
?>

Podałem w komentarzach także sposób na sprawdzenie czy użytkownik jest zalogowany:

if (Auth::instance()->logged_in()){

wyciągnięcie id zalogowanego:

Auth::instance()->get_user();

sprawdzenie czy jest adminem:

if (Auth::instance()->logged_in('admin')) {

Podczas rejestracji możemy od razu zapisać role, rola 1 to login:

$role = ORM::factory('role','1');
$client->add('roles',$role);
$client->save();

6. Widok dla logowania (/application/views/login.php)

 
<h2><?php echo $title?></h2>
<?php
echo  Form::open('/auth/login', array('class'=>'form')).
'<fieldset>'.
    '<legend>'.__('Fill the fields').'</legend>'.
            //$error.
            Form::label('username', __('Nick').':').
            Form::input('username').'<br />'.
 
            Form::label('password', __('Password').':').
            Form::password('password').'<br />'.
 
'</fieldset>'.
Form::submit('submit', __('Login')).
Form::close();
?>

I tak oto, w kilku krokach uruchomiliśmy moduł Auth. Należałoby jeszcze utworzyć rejestrację z formularza, ale do tego warto by wykorzystać walidację pól, co może być tematem na kolejny wpis :)
Tworząc pewne akcje (np. dodawanie artykułów, usuwanie użytkowników, funkcje moda czy admina), należy sprawdzać, czy dany użytkownik ma prawo (rolę) do ich wykonywania!

55 Odpowiedzi :“Logowanie z Auth”

  1. :) Krótko i na temat tak powinno być dzięki podoba mi się .

  2. Mariusz wykonujesz kawał dobrej roboty , i chwała ci za to :)

  3. Mariusz napisał:

    Thx :D Dobrze, że przydają się moje porady… Z doświadczenia wiem, że początki bywają trudne, a celem blogu jest ich ułatwienie. W ramach wyczerpywania podstawowych tematów, mam zamiar zająć się opisem bardziej złożonych rzeczy, a także tworzeniem i opisem dodatkowych modułów czy kompletnych rozwiązań.

  4. blizz napisał:

    Good job! Ciekawe wpisy wszystkie, czasem mógłbyś podać więcej przykładów, np. logowanie z zapamiętywaniem(taka tylko propozycja :P ). Mnie osobiście ciekawiłby wpis o cache’u, przy małych portalach, czy stronach niepotrzebne, ale przy większych już tak.
    Pozdrawiam i życzę wytrwałości, bo ciekawie się zapowiada!

  5. Destrix napisał:

    Świetny poradnik, dzięki! duzo pomógł i w końcu wiem na czym stoję z auth. Teraz chyba czas na poradnik o validacji pól bo póki co to też przyprawia mnie o ból głowy. :) Pozdrawiam.

  6. Avenin napisał:

    Pierwszy raz w życiu cokolwiek komentuje, ale aż na taki gest się zdobyłem ponieważ pierwszy raz widze coś napisanego przez kogoś na temat frameworków bez p…lenia, prosto, konkretnie i bez udziwnień. Jasno i klarownie. Wielkie dzięki!

  7. tojach napisał:

    Dużo pomógł mi ten wpis :D szczególnie jeśli chodzi o role. Teraz wiem co i jak. Dziekowac

  8. Kedan napisał:

    Tylko czy jest sens trzymać w hash_key wynik hash_hmac()? Tam powinien być po prostu tajny klucz. hash_hmac() wywoływane jest w Auth::hash()

    • Mariusz napisał:

      Nie ma. Jak jest tworzony hash_key nie koniecznie należy przechowywać w configu, jedynie wynik działania funkcji hash_hmac.
      Pokazałem jedynie jak utworzyć taki klucz.

  9. ok to rozumiem:

    $client = ORM::factory('user');
    $client->email = "admin@email.com";
    $client->username = "admin";
    $client->password = "admin";
    $client->save();
    

    ale nie rozumiem tego:

    $role = ORM::factory('role','1');
    $client->add('roles',$role);
    $client->save();
    

    a mianowicie jak to dziala.

    Po wykonaniu $client->save(); dodaje sie nowy wpis do users, to jest zrozumiale. $role = ORM::factory(‚role’, ’1′); pobiera z bazy role o indeksie 1 czyli domyslnie ‚login’.

    Wiec moje glowne pytanie co robi $client->add(‚roles’, $role);? Dodaje do roles_users nowy wpis laczacy id userow i roli?

    • Mariusz napisał:

      Wiec moje glowne pytanie co robi $client->add(‘roles’, $role);? Dodaje do roles_users nowy wpis laczacy id userow i roli?
      Dokładnie to robi.
      Podobny efekt bez ORM można by uzyskać wywołując

      $id=$client->save();
      DB::query(2,'INSERT INTO `roles_users` (`user_id`,`role_id`) VALUES ('.$id.',1)')->execute();
      //
      
    • Juz chyba lepiej intuicyjnie uzyc czystego SQLa ;) ale to moja opinia tylko ;)

      Dzieki za odpowiedz, pozdrawiam

  10. Mam jeszcze problem z logowaniem.
    Po wykonaniu:

    $r = Auth::instance()->login($username, $password, TRUE);
    

    Zawsze zwraca mi FALSE.

    Po bardziej szczegolowych badaniach wyszlo mi, ze po zahaszowaniu podczas rejestracji, haslo calkiem inaczej zapisuje sie w bazie danych. Sytuacja dotyczy kohany w wersji 3.2.

    Sprawdzalem w modules/orm/classes/kohana/auth/orm.php. Na instrukcje przed porownaniem haszow stawialem die($password) i die($user->password).
    Dla wyrazenia „rakoo” hasz z bazy to:
    0c7673c24d95e96705983f980fe2d9915e0925fd7e4d1acfb858676cdb056905, a normalny z funkcji hasz 6ff16b8162ce37bec6df93ad5c5198e99f7c1fb5cb40eeade10681ecf2875dc3.

    Zaczynam sie zastanawiac czy wlasnorecznie nie napisac klasy obslugi logowania opartej na sesji ;/

    • Ok problem rozwiazany. Chyba w 3.2 maja jakiegos buga, albo czegos nie doczytalem. Podczas zakladania konta wychodzi na to, ze haslo jest haszowanie podwojnie.
      W logowaniu przekazalem funkcji logujacej zamiast czyste haslo, jego hasz i zadzialalo.
      Potem nalezy tez ustawic cookie salt w bootstrap.php:

      // -- Configuration and initialization --
      
      /**
       * Set the default language
       */
      // I18n::lang('en-us');
      I18n::lang('pl');
      
      Cookie::$salt = 'twoje cookie salt!';
      
      • Mateusz napisał:

        Mi natomiast ciągle nie udaje się zalogować ;/ Próbowałem przesyłać hashowane hasło, dodałem do bootstrapa jakieś cookie::$salt i ciągle nic… możliwe, że kohana 3.2 ma jakiegoś buga w tym module

        • Mariusz napisał:

          A nie zmieniałeś hasha w configu jak są już jacyś użytkownicy? Jeśli użytkownik się zarejestrował, a Ty później zmieniłeś hash w configu to podczas logowania hash hasła jest różny od tego zapisanego w bazie i logowanie się nie powiedzie. Spróbuj zarejestrować nowego użytkownika i zalogować się na niego. Upewnij się czy użytkownik ma rolę login!

          PS.
          Kilka osób pytało o skrypt blogu na KO3.2, takowy właśnie powstaje..

    • Mariusz napisał:

      Podwójne hashowanie (nawet nie w Auth) zapewnia m.in. to, że w przypadku przejęcia danych z bazy, rozszyfrowanie metodą brutal force jest utrudnione.
      Załóżmy, że hasło w bazie to wynik funkcji jednokierunkowej md5(hasło). Gdyby ktoś uzyskał taki hash to może on ‚rozszyfrować’ go, dzięki dostępnym w internecie porównywarkom md5 (porównują hashe z zapisanym wcześniej i potrafią odczytać wiele haseł). Podwójne zahashowanie md5(md5(hasło)) sprawia, że odczytanie komplikuje się wykładniczo.
      Moduł Auth dodatkowo dzięki ‚mieszaniu’ kluczem hashującym jest bardzo bezpiecznym i prostym modułem logowania.

      • Gdzies nawet kiedys czytalem, ze udalo sie za pomoca klastrow play station 3 tworzyc kolizje md5 – 2 rozne ciagi wejsciowe daja ten sam hasz wyjsciowy, ale to juz offtopic :) .

  11. Jeśli kogoś interesuje stworzenie własnych uprawnień a nie tylko korzystać z tych, które są wpisane bazie czyli „login”, „admin” to powinien zwrócić uwagę na plik orm.php. Jest tam taka linia:

    if ($user->has(‘roles’, ORM::factory(‘role’, array(‘name’ => ‘login’))) AND $user->password === $password)
    

    Jeśli stworzymy listę własnych uprawnień w bazie (w tabeli roles) i zamiast „login” wpiszemy np „zwyklyuser” to powinniśmy poprawić to także w tym pliku orm.php na

    array(‘name’ => ‘zwyklyuser’)
    

    W przeciwnym przypadku kohana nie zaloguje nam uzytkownika.

    • Mariusz napisał:

      Rola login oznacza możliwość logowania, rola admin nie ma zdefiniowanych żadnych uprawnień. Sami musimy zaprogramować

      if (Auth::instance()->logged_in('admin')) {
      // np. usuwanie, banowanie użytkowników
      }
      

      Jeśli dodamy do bazy nową rolę, np. mod to nic to nie oznacza, sami musimy zaprogramować co może robić mod, to samo tyczy się admina. Trzeba się najpierw zastanowić nad uprawnieniami i funkcjami a potem w warunkach if sprawdzać czy zalogowany może z tego korzystać, czy nie.

      • Tak, zgadzam się z Tobą, ale ja pisałem o czymś innym.
        Miałem na myśli sytuację, kiedy chcemy zrezygnować ze standardowego uprawnienia „login” – wyrzucić je z bazy i zastąpić własnym – np „zwyklyuser”. Wtedy trzeba też dokonać zmiany w pliku orm.php w wyżej podanym przeze mnie fragmencie kodu aby kohana w ogóle nas zalogowała. Jeśli zmienisz uprawnienie „login” w bazie na jakieś inne to bez w/w zmian nie zostaniesz zalogowany.

  12. Rafał napisał:

    Na początku słowa uznania za wiedze i chęci w przekazywaniu jej innym

    A teraz pytanko. W tym module są uprawnienia (role) login i admin jak pisałeś admnin nie jest zdefiniowany i samemu trzeba tam jakos to oprogramować a co z loginem czy linijka

    $r = Auth::instance()->login($_POST['username'], $_POST['password']);
    

    automatycznie sprawdza czy dany użytkownik już może się logować czy gdzieś to jest indziej.

    • Mariusz napisał:

      Jeśli użytkownik ma rolę login, to może się logować, jeśli nie ma to nie może.
      Rolę tą można dodawać od razu po zarejestrowaniu (dodanie użytkownika do bazy nie musi oznaczać dodania roli login), albo wysłać e-maila z linkiem i hashem, jeśli użytkownik kliknie, to sprawdzić hash z linku z tym w bazie i jeśli się zgadza wtedy dopiero dodać mu rolę login.
      Jeśli użytkownik jest zalogowany (ma rolę login) to np. może dodawać artykuły, jeśli jest adminem może np. usuwać użytkowników. Najlepiej sprawdzać ifami na początku akcji czy dana osoba ma do niej prawo.

      • raf_79 napisał:

        dzięki za szybką odpowiedź.

        ok to rozumiem, ale w którym miejscu jest fizycznie sprawdzane czy dany użytkownik ma daną rolę ( w tym przypadku login)

      • Mariusz napisał:

        Sprawdzane jest podczas logowania, w momencie wywołania funkcji login modułu Auth:

        Auth::instance()->login();
        

        Jeśli ma rolę login to się zaloguje, jeśli nie ma, to logowanie się nie powiedzie (przy okazji przypominam, że admin musi mieć obydwie role).

        Można później również sprawdzać czy jest zalogowany:

        if (Auth::instance()->logged_in()){
            //zalogowany
        }
        
      • raf_79 napisał:

        ok dzięki to już ostatnie pytanie :)
        jak w takim razie sprawdzić czy ma się np. role del, która zezwala załóżmy na kasowanie postów.

      • Mariusz napisał:

        W analogiczny sposób co do roli admin:

        if (Auth::instance()->logged_in('del')) {
            //rola del
        }
        
  13. white napisał:

    Witam,

    jak zrobić aby było widać dane użytkownika wszędzie nie tylko w kontrolerze auth ? Dzięki

    • Mariusz napisał:

      Kontroler Auth jest do rejestracji/logowania/wylogowywania. Do danych zalogowanego użytkownika można się dostać wszędzie (np. w innych kontrolerach/widokach) poprzez klasę Auth:

      Auth::instance()->get_user();
      

      Wyciągnąć nazwę użytkownika możemy przez:

      Auth::instance()->get_user()->username;
      
  14. white napisał:

    ok dzieki dzięki mam jeszcze kilka pytanek :P

    W jaki sposob przypisywać dane z ‚zewnątrz’ (post/get)?
    czy po validacji wystarczy

    $this->property = $_POST['key']

    czy lepeij np. Arr::get(array, key) ?

    • Mariusz napisał:

      Jeśli dane pochodzą z formularza u nas na stronie to odbieramy _post. Do modelu przesyłamy całą tablicę:

      $model->save_data($_POST);
      

      A w modelu odwołujemy się do $data – bezpośrednio, albo przy pomocy helpera Arr (bez znaczenia):

      public function save_data($data){
        $this->property = $data['key'];
      }
      

      Przy zapisywaniu można np. usunąć zbędne znaczniki HTML, z inputa.

  15. white napisał:

    Jaki bajerek jest jeszcze do aktywacji użytkowników przez e-mail ?

    • Mariusz napisał:

      Chodzi o klasę do wysyłania maili, czy jak tworzyć, sprawdzać hash i dodawać rolę logowania po prawidłowej weryfikacji?

      • white napisał:

        Bardzo dziękuję za odpowiedzi na pytania ;)

        byłem ciekaw czy jest własnie jakaś klasa/modul do zrobienia np. aktywacji uzytkownikow / przypominania hasła , czy będę to musiał pisać od podstaw.

        A co do tego modelu w widoku, to właśnie mam pewną niejasność albo źle zinterpretowałem bloga http://www.zyxist.com/pokaz.php/poeksperymentujmy_z_mvc

        jest tam coś np. w stylu

        Do serwera przychodzi żądanie HTTP.
        Serwer odpala skrypt PHP.
        Skrypt PHP odpala kontroler.
        Kontroler patrzy, co od niego chcemy w żądaniu.
        Kontroler odpala żądaną akcję.
        Akcja wybiera model oraz widok.
        [b]Widok pobiera dane z modelu.[/b]
        Widok generuje odpowiedź (np. kod HTML).
        Widok przekazuje odpowiedź HTTP do serwera.

        troche sam sobie problemów szukam, ale chciałbym poprawnie wykorzystywać wzorce oraz framework, a z tym na początku są problemy

      • Mariusz napisał:

        Może autor artykułu trochę niejasno się wyraził:

        Akcja wybiera model oraz widok.
        Widok pobiera dane z modelu.
        

        Powiedziałbym:

        W akcji możemy wybrać modele i wczytujemy widoki.
        Do widoku przesyłamy obiekty/tablice i je wyświetlamy.
        

        Klasę do wysyłania maili oraz przykładową procedurę rejestracji opiszę wkrótce ;)

  16. white napisał:

    i jeszcze jedno (przepraszam za osobne komentarze)

    jeśli to wszystko to (H)MVC to kiedy odwoływać się w Widoku do Modelu ?
    do tej pory przesyłałem tylko wynik jakiejs metody z modelu kontrolerem do widoku.

    • Mariusz napisał:

      W widokach raczej nie powinniśmy odwoływać się bezpośrednio do modelu, tylko właśnie przez kontroler. A dzięki HMVC możemy np. pojedynczym zapytaniem utworzyć kilka innych, polecam artykuł HMVC.

  17. Michał napisał:

    Witam, pierwszy raz piszę stronę z logowaniem i w php jestem praktycznie zielony. Mógłby mi ktoś na przykładzie co wpisać w hash_method i hash_key() w congig/auth.php i jak to się ma do tego co będzie przechowywane w bazie danych w polu „password”.

    • Mariusz napisał:

      Najlepiej w przypadku gdy nie jesteśmy pewni jak coś dział zobaczyć jak wygląda wywołanie metody za to odpowiadającej.
      Przy tworzeniu pola password w bazie, wykorzystywana jest funkcja hash() klasy Kohana_Auth, która zwraca wynik z funkcji php hash_hmac:

      hash_hmac($algo, $data, $key)
      

      tworzy ona hash z podanych danych: jako pierwszy parametr przyjmuje algorytm (np. md5), jako drugi ciąg znaków do zahashowania (np. hasło), jako trzeci przyjmuje tajny klucz do generowania hasha.

      Popatrzmy zatem jak to jest w klasie Kohany:

      return hash_hmac($this->_config['hash_method'], $str, $this->_config['hash_key']);
      

      Jak widać jako pierwszy parametr pobierana jest z configu funkcja, jako drugi przesłany parametr do funkcji, a jako trzeci tajny klucz z configu.

      • Michał napisał:

        Dzięki za tak szybką odpowiedź, już wszystko ładnie działa. Po prostu niepotrzebnie sam hashowałem hasło i się nie zgadzało. Bardzo fajny blog. Pozdrawiam :)

  18. grammy napisał:

    Witam.

    Próbował ktoś pobrać informacje o użytkownikach (łącząc tablele – users, roles i users_roles) tak, żeby w jednym zapytaniu uzyskać rekordy:

    id (usera), username, email (z users), id (roli), name (z roles), np.:

    1 | user1 | email1@email1.pl | 1 | login
    2 | user2 | email2@email2.pl | 2 | admin

    a nie np.:

    1 | user1 | email1@email1.pl | 1 | login
    2 | user2 | email2@email2.pl | 1 | login
    2 | user2 | email2@email2.pl | 2 | admin

    czyli wyświetlać każdego użytkownika raz i największy stopień uprawnienia jaki posiada. Wydaje się proste ale żadne funkcje grupujące ani wybieranie wartości max czy podzapytania nie dały rezultatu, może ktoś będzie wiedział?

    Pozdrawiam

    • Mariusz napisał:

      Np. stosując zapytanie:

      SELECT `id`, `username`, `email`, (SELECT `role_id` FROM `roles_users` WHERE `users`.`id`=`roles_users`.`user_id` ORDER BY `role_id` DESC LIMIT 1) AS `max_role`, (SELECT `name` FROM `roles` WHERE `roles`.`id`=`max_role`) AS `max_role_name` FROM `users`
      

      Tylko czy dodawałeś role wg uprawnień? (bo to pobierze największe id).

      To nie wykorzystujesz modułu Auth do sprawdzania roli zalogowanego?

      if (Auth::instance()->logged_in('mod')) {
          echo 'to jest moderator';
      }
      
      • grammy napisał:

        Dzięki wielkie, w ten sposób nie próbowałem, działa bez zarzutu. Rolę zalogowanego użytkownika sprawdzam tak jak napisałeś, tamto zapytanie potrzebuję do wyświetlenia wszystkich userów jacy są w bazie (tylko raz z największym uprawnieniem jaki posiada) w celu zarządzania nimi. Tak jak zauważyłeś, żeby to było logiczne rola dająca większe uprawnienia musi mieć wyższe id (co też doskonałe nie jest, w takim przypadku może lepiej dodać do roles kolumnę, która określałaby poziom uprawnienia, np. login miałby level 1, admin 3, mod 2 itp., wtedy nie trzeba byłoby polegać na polu id w tabeli roles – ale mniejsza z tym, nie jest to jakaś szczególna konieczność dla problemów poruszanych w tym artykule).
        Pozdrawiam i dziękuję Ci jeszcze raz.

  19. Adam napisał:

    Witam, mógłbyś wyjaśnić jak zrobić, aby logujący się użytkownik, mógł zostać zapamiętany w przeglądarce na przykład na miesiąc? Do tej pory, gdy się loguję, zamknę przeglądarkę to następuje wylogowywanie. O dziwo trzeci parametr funkcji logującej nic nie zmienia :(

    Auth::instance()->login($username, $password, TRUE);

    Liczę na odpowiedź, bo nie mogę się z tym uporać kilka dni. Pozdrawiam.

    • Mariusz napisał:

      A czy w bootstrapie masz zdefiniowane cookie salt?

      Cookie::$salt = md5('your secret is safe with me') ;
      

      Ten salt to tajny ciąg znaków potrzebny do działania Cookie – tu akurat wyznaczam go funkcją md5() z ciągu znaków.

      Przy okazji zamiast zawsze TRUE, lepiej dodać check’a i sprawdzać:

      Auth::instance()->login($_POST['username'], $_POST['password'], Arr::get($_POST, 'remember')=='on' ? TRUE : FALSE);
      
  20. Adam napisał:

    Dzięki za szybką odpowiedź. Cookie::salt mam zdefiniowane w bootstrapie. Mam też to zrobione na checkbox’a, ale najpierw chcę zrobić, aby jakkolwiek działało.

    Dokopałem się do funkcji login() i tam jest w komentarzu nad nią napisane iż $remember_me – not supported i w dodatku nic sie dzieje dalej z tym trzecim parametrem funkcji…

    Zauważyłem też iż w bazie danych, tabela users_tokens nie jest zupełnie wykorzystywana.

    Tobie działa normalnie zapamiętywanie?

    • Mariusz napisał:

      Jaką masz wersję Kohany? U mnie działa bez problemów zapamiętywanie i jak zapamięta, to właśnie w bazie tworzy token. Może w przeglądarce masz cookie wyłączone? Podaj ścieżkę do pliku w którym tak pisze.

      • Adam napisał:

        Cookie mam oczywiscie włączone w przeglądarce :) Kohana 3.2.

        Z tym not-supported to sorry, okazało się, że przeglądałem plik file.php, gdzie też jest funkcja login().

        Jednak mimo wszystko tworzenie tego tokenu nie następuje. Później przysiądę i poszukam co może być przyczyną, skoro to tylko u mnie występuje.

        Dzięki za odpowiedzi.

      • Adam napisał:

        OK juz wiem w czym lezał problem. Chodzi o to, ze używam sterownika bazy danych PDO, a on wymaga, aby w kazdym modelu byla zdefiniowana lista kolumn.

        Wystarczylo dodac w klasie Model_Auth_User_Token nastepujacą tablicę:

           protected $_table_columns = array(
                'id' 			=> array('type' => 'int', 		'is_nullable' => false),
                'user_id' 		=> array('type' => 'int', 		'is_nullable' => false),
                'user_agent' 		=> array('type' => 'string', 	'is_nullable' => false),
                'token' 		=> array('type' => 'string', 	'is_nullable' => false),
                'type' 		=> array('type' => 'string', 	'is_nullable' => false),
                'created' 		=> array('type' => 'int', 		'is_nullable' => false),
                'expires' 		=> array('type' => 'int', 		'is_nullable' => false),
            );

        Może się komuś przyda na przyszłość :) pozdro

  21. Kamil napisał:

    tak się zastanawiam czy nie lepiej używać klasy database czy db buildera. W teorii powinny być szybsze niż orm. A ty jak uważasz ORM czy database (nie mówię o PDO)

    • Mariusz napisał:

      Tak, ORM nie jest zbyt wydajny, ale do większości mniejszych i średnich serwisów się nadaje. Szybko się w nim pisze, a różnicę byłoby widać dopiero w skomplikowanych zapytaniach i przy bardzo dużej liczbie wejść na stronę. Ja ORM używam do dodawania/edycji rzeczy do bazy, a do wyciągania skomplikowanych zapytań używam DB.

  22. Bartek napisał:

    mam takie pytanie. mam problem z sesja. zmienna z danymi uzytkownika po przekierowaniu po zalogowaniu znika. uzywam konfiguracji native. moze kiedys zetknales sie z podobnym problemem

    • Mariusz napisał:

      Wyłącz na razie przekierowanie i spróbuj zdebugować czy w ogóle się loguje (co zwraca login() i co ew. siedzi w sesji):

      $r = Auth::instance()->login($_POST['username'], $_POST['password']);
      
      echo Debug::vars($r, $_SESSION);
      
  23. Bartek napisał:

    przeszedlem na sesje w bazie. okazalo sie ze ciasteczka nie zapisuja sie w $_COOKIE. nie mam pojecia czemu. dalej sesja dziala tylko do przekierowania. wszystko dziala ok do momentu zapisania i oczytania ciasteczka

Dodaj komentarz

Dodając kod PHP używaj tagów: [php][/php]

*