Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ZendFramework] Logowanie użytkownika
Forum PHP.pl > Forum > PHP > Frameworki
in5ane
Cześć, chciałbym się dowiedzieć, czy idę w dobrym kierunku tworząc logowanie w Zend Frameworku. Tzn. ogólnie rzecz biorąc, czy to jest dopuszczalne takie logowanie i czy to będzie dobrze działać. Proszę o opinie oraz o dodatkowe pomoce, czy jakieś przykłady waszych logowanie lub szablony.

  1. <?php
  2. function loginAction() {
  3.        $this->view->title = "Twoje konto";
  4.        
  5.        if ($this->_request->isPost()) {
  6.            $filter = new Zend_Filter_StripTags();
  7.            $login = trim($filter->filter($this->_request->getPost('login')));
  8.            $password = md5(trim($filter->filter($this->_request->getPost('password'))));
  9.            
  10.            if ($login != '' && $password != '') {
  11.                $check = new account();
  12.                $select_check = $check->select()->where('login = "'.$login.'" AND password = "'.$password.'"');
  13.                $this->view->patrz = $select_check;
  14.                $row_check = $check->fetchRow($select_check);
  15.                $login = $row_check->login;
  16.                $type = $row_check->type;
  17.                $check = count($row_check);
  18.                if ($check != '') {
  19.                    session_start();
  20.                    if (!isset($_SESSION['zalogowany'])) {
  21.                        ///utworzenie sesji, bla bla bla... do dopisania
  22.                    }
  23.                } else {
  24.                    $this->view->warning = '<font style="color: #ff0000; font-weight: bold;">Wpisane dane są niepoprawne.</font><br /><br />';
  25.                }
  26.            } else {
  27.                $this->view->warning = '<font style="color: #ff0000; font-weight: bold;">Nie wypełniłeś wszystkich pól.</font><br /><br />';
  28.            }
  29.            
  30.        }
  31.  
  32.        $this->view->action = 'login';
  33.        $this->view->buttonText = 'Zaloguj się';
  34.    }
  35. ?>
luki100011
Raczej nie

Masz komponent Zend_Auth który się tym zajmuje.
seth-kk
na pierwszy rzut oka ten kod nie jest odpowrny na sql injection
rzuc okiem na przyklady z manuala
melkorm
W dodatku zapoznaj się z Zend_Form'em - odpadnie Tobie cała 'ręczna' walidacja i jak już koledzy wspomnieli Zend_Auth.

Kilka uwag:
1. Używasz Zenda, tak ? To dlaczego nie wykorzystujesz jego dobrodziejstw tylko piszesz wszystko na piechte - szczerze na peichte to byś to szybciej napisał bez Zenda smile.gif
2. Zainteresuj się modelami i Zend_Db_Table i pobieranie danych wykonuj w modelu - po to został on stworzony.
3. Używając Zend_Db_Table razem z Zend_Formem odporny jesteś na SqlInjection.

Sądze że to troche pomoże ... bo np. do loginu możesz dorzucić validator (używając Zend_Form'a) i już sam Zend sparwdzi czy login istnieje w bazie dancyh i w razie co wypluje sam błęda smile.gif (odrazy odsyłam do Zend_Translate - jest to opisane przy Validatorach jak tłumaczyć wiadomości rzucane przez Zenda).
in5ane
Trochę nie zrozumiałem tego pierwszego zdania. Jeżeli użyję Zend _Form, to już nie muszę używać Zend_Auth?
batman
Zend_From używasz do stworzenia formularza, a Zend_Auth do logowania użytkownika.
nospor
zend_form - obsluga formularzy, walidacja, itp.
zend_auth - obsluga autoryzacji

jedno nie ma związku z drugim, ale oba mozesz uzywac jendoczesnie. jesli uzywasz ZendFramework, to jest to nawet wskazane, bys uzywal tych obu klas. Ale nadal kazda z nich sluzy do czego innego smile.gif
nexis
Cytat(in5ane @ 30.06.2009, 11:13:59 ) *
Trochę nie zrozumiałem tego pierwszego zdania. Jeżeli użyję Zend _Form, to już nie muszę używać Zend_Auth?

Zend_Form jak sama nazwa mówi służy do tworzenia formularzy. Do walidacji pól użyj dodatkowo Zend_Validation, który z łatwością integruje się z Zend_Form. A na sam koniec połącz to z Zend_Auth, który przeprowadzi odpowiednie sprawdzenie czy wprowadzone dane zgadzają się z tymi zapisanymi w serwisie.
in5ane
Czy logowanie tego typu dobrze będzie (to dopiero początek):

AccountController.php:
  1. <?php
  2. class AccountController extends Zend_Controller_Action {
  3.  
  4.    function init() {
  5.        $this->view->baseUrl = $this->_request->getBaseUrl();
  6.    }
  7.    
  8.    function getForm() {
  9.        $form = new Zend_Form();
  10.        $form->setAction('/account')->setMethod('post');
  11.  
  12.        $login = $form->createElement('text', 'login', array('label' => 'Login'));
  13.        $login->setRequired(true)
  14.                ->addValidator('NotEmpty', true, array('messages' => array('isEmpty' => 'Nie wpisałeś/aś loginu.')))
  15.                ->addValidator('stringLength', false, array(6, 12, 'messages' => array('stringLengthTooShort' => 'Wpisany login jest za krótki.', 'stringLengthTooLong' => 'Wpisany login jest za długi.')))
  16.                ->addDecorators(array(array('Label', array('class' => 'zf-label')), array('HtmlTag', array('class' => 'zf-description')), array('Errors', array('class' => 'zf-errors'))));
  17.  
  18.        $password = $form->createElement('password', 'password', array('label' => 'Hasło'));
  19.        $password->setRequired(true)
  20.                ->addValidator('NotEmpty', true, array('messages' => array('isEmpty' => 'Nie wpisałeś/aś hasła.')))
  21.                ->addValidator('stringLength', false, array(6, 12, 'messages' => array('stringLengthTooShort' => 'Wpisane hasło jest za krótkie.', 'stringLengthTooLong' => 'Wpisane hasło jest za długie.')))
  22.                ->addDecorators(array(array('Label', array('class' => 'zf-label')), array('Errors', array('class' => 'zf-errors'))));
  23.  
  24.        $form->addElements(array($login, $password))->addElement('submit', 'log', array('label' => 'Zaloguj się'));
  25.        
  26.        return $form;
  27.    }
  28.    
  29.    function indexAction() {
  30.        $this->view->title = "Twoje konto :: Logowanie";
  31.        
  32.        $form = $this->getForm();
  33.        
  34.        if ($this->_request->isPost()) {
  35.            $formData = $this->_request->getPost();
  36.            if ($form->isValid($formData)) {
  37.                $objDbAdapter = new Zend_Db_Adapter_Pdo_Mysql(array('host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'zend'));
  38.                $objAuthAdapter = new Zend_Auth_Adapter_DbTable($objDbAdapter, 'users', 'login', 'password', 'MD5(?)');
  39.                $objAuthAdapter->setIdentity($this->_getParam('login'))->setCredential($this->_getParam('password'));
  40.                $objAuth = Zend_Auth::getInstance();
  41.                $objResult = $objAuth->authenticate($objAuthAdapter);
  42.                if ($objResult->isValid()) {
  43.                    $data = $objAuthAdapter->getResultRowObject(null, 'password');
  44.                    $objAuth->getStorage()->write($data);
  45.                    $this->_redirect('/account/login');
  46.                } else {
  47.                    $this->view->message = '<p class="zf-errors" style="margin-bottom: 10px;">Logowanie nie powiodło się.</p>';
  48.                }
  49.  
  50.            }
  51.        }
  52.        
  53.        $this->view->form = $form;
  54.    }
  55.  
  56.    function loginAction() {
  57.        $this->view->title = "Twoje konto :: Zalogowany";
  58.        $this->view->user = Zend_Auth::getInstance()->getIdentity();
  59.    }
  60.  
  61.    function logoutAction() {
  62.        Zend_Auth::getInstance()->clearIdentity();
  63.        $this->_redirect('/');
  64.    }
  65. ?>


index.phtml
  1. <?php echo $this->message; ?>
  2. <?php echo $this->form; ?>


login.phtml
  1. <?php if($this->user) : ?>
  2.        Jesteś zalogowany jako: <?php echo $this->user->login; ?>.<br /><br />
  3.        <a href="<?php echo $this->baseUrl ?>/account/logout">Wyloguj się.</a>
  4.    <?php endif; ?>


style.css
Kod
w stylach użyłem zf-label, zf-description oraz zf-errors


Czy to co zacząłem jest dobrze?

@edit: dopisałem zend_auth. W sumie wszystko działa, ale jak to wygląda od kodu, jest to dość poprawnie?
pgrzelka
czemu tworzysz klasę bazy w kontrolerze ?
nie lepiej w bootstrapie?

potem zapisujesz ją np. w Zend_Registry::set('db', $db);
i w kontrolerze odczytujesz $db = Zend_Registry::get('db');

bazę możesz również odczytać w taki sposób $db = Zend_Db_Table::getDefaultAdapter(); (oczywiście jeśli ustawiłeś wcześniej w boostrapie domyślny adapter bazy)
in5ane
OK, a tak to poza tym wszystkim dobrze i ładnie napisane?

Chciałbym się też dowiedzieć, jak za pomocą zend_form, mógłbym sobie ułożyć formularz wedle swojego uznania.

Oraz chciałbym się dowiedzieć, jak mogę ustawić, żeby powiedzmy błędy nie pokazywały się pod danym polem, tylko każdy błąd nad formularzem.
batman
Od tego masz dekoratory.
in5ane
Cytat(batman @ 2.07.2009, 13:32:46 ) *
Od tego masz dekoratory.


Trochę średnio rozumiem to, z tej dokumentacji.

Powiedzmy, że ten wygląd zrobię tak (jak jest tam):
  1. <?php
  2. class My_Decorator_Composite extends Zend_Form_Decorator_Abstract
  3. {
  4.     public function buildLabel()
  5.    {
  6. ..........................................................
  7. }
  8. ?>

Aha i gdzie mam umieścić ten plik dokładnie?

Później chcę wykorzystać to do wszystkich pól, no to:
  1. <?php
  2. $form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');
  3. ?>


No i nic się nie dzieje, a ustawiłem dla testu, że przed każdym errorem powinno się wyświetlić jakieś "asdasd".

Wie ktoś może jak dobrze używać tych własnych dekoratorów?
batman
Cytat(in5ane @ 6.07.2009, 07:16:59 ) *
Wie ktoś może jak dobrze używać tych własnych dekoratorów?
Ja wiem. Ale nie po to podałem Ci linka, byś teraz zawracał 4 litery i podbijał temat. Jeśli coś Ci nie działa, to użyj google, wpisz zend form decorator, poczytaj i dopiero potem zacznij marudzić.
in5ane
Cytat(batman @ 6.07.2009, 06:47:06 ) *
Ja wiem. Ale nie po to podałem Ci linka, byś teraz zawracał 4 litery i podbijał temat. Jeśli coś Ci nie działa, to użyj google, wpisz zend form decorator, poczytaj i dopiero potem zacznij marudzić.


Kolego, no właśnie w tym rzecz, że szukałem i nic nie mogłem znaleźć, a że topic spadał sporo w dół, to go podbijałem, bo możliwe, że ktoś nie zauważył i mi dlatego nie mógł pomóc. Jeszcze spróbuję poszukać, ale jakby co, to proszę o pomoc.
melkorm
nie umiesz dekoratorów , nie rozumiesz manuala, to zrób inaczej, przeklej do tmpl to co ywpluwa Tobie Zend_Form dorzuć reportowanie błędów przez:
  1. <?php
  2. $form->getElement('nazwa_pola')->getMessages(); //zwraca tablicę
  3. ?>


Wystarczy że ozstawisz dobre nazy pól inputów / forma i Zend_Form będzie działał tak smao jakbyś zrobił:

  1. <?php
  2. echo $this->form;
  3. ?>

I teraz możesz sobie to normalnie stylwoac bez przeszkód.

Szczerze nie odpowiadałem na ten wątek bo nie miałem czasu i troche chęci, troche ciężko co chwila komuś tłumaczyć manuala snitch.gif
in5ane
@up: właśnie mnie chodzi o to, aby ogarnąć te dekoratory. Ale z tego manuala, źle je zrozumiałem ;/
melkorm
Ja sam nie używam dekoratorów (jeszcze nie zdażyło mi się użyc tongue.gif), po stronie admina używam Zend_Form (przerobiłem go na własne potrzeby) normalnie, ale po stronie frontendu wpisuje ręcznie - o wiele łatwiej wtedy to ostylować.

A jak nie rozumiesz dekoratorów (imho jest krok po kroku napsiane co i jak) no to nie oczekuj od Nas że będziemy Tobie wszystko tłumaczyć winksmiley.jpg Jeżeli nie ogarniasz Zenda to daj sobie spokój i weź się za jakiś prostrzy framework bo Zend jest ciężki (może to troche za dużo powiedziane ...) ;]
batman
Cytat(in5ane @ 6.07.2009, 11:38:48 ) *
no właśnie w tym rzecz, że szukałem i nic nie mogłem znaleźć
Pierwszy wynik - http://devzone.zend.com/article/3450
trzeci wynik - http://bethgranter.wordpress.com/2008/04/2...tom-decorators/

Coś kiepsko szukałeś. Wszystko jest jasno i dokładnie opisane. Jedyne co trzeba zrobić to poszukać.
in5ane
Dzięki. A mam pytanie, czy to logowanie, które napisałem jest już poprawne i zabezpieczone:
  1. <?php
  2. function getForm() {
  3.        $form = new Zend_Form();
  4.        $form->setAction('/account')->setMethod('post');        
  5.  
  6.        $login = $form->createElement('text', 'login', array('label' => 'Login'));
  7.        $login->setRequired(true)
  8.                ->addValidator('NotEmpty', true, array('messages' => array('isEmpty' => 'Nie wpisałeś/aś loginu.')))
  9.                ->addValidator('stringLength', false, array(6, 12, 'messages' => array('stringLengthTooShort' => 'Wpisany login jest za krótki.', 'stringLengthTooLong' => 'Wpisany login jest za długi.')))
  10.                ->addDecorators(array(array('Label', array('class' => 'zf-label')), array('HtmlTag', array('class' => 'zf-htmltag')), array('Errors', array('class' => 'zf-errors'))));
  11.  
  12.        $password = $form->createElement('password', 'password', array('label' => 'Hasło'));
  13.        $password->setRequired(true)
  14.                ->addValidator('NotEmpty', true, array('messages' => array('isEmpty' => 'Nie wpisałeś/aś hasła.')))
  15.                ->addValidator('stringLength', false, array(6, 20, 'messages' => array('stringLengthTooShort' => 'Wpisane hasło jest za krótkie.', 'stringLengthTooLong' => 'Wpisane hasło jest za długie.')))
  16.                ->addDecorators(array(array('Label', array('class' => 'zf-label')), array('HtmlTag', array('class' => 'zf-htmltag')), array('Errors', array('class' => 'zf-errors'))));
  17.  
  18.        $submit = $form->createElement('submit', 'log', array('label' => 'Zaloguj się'));
  19.        $submit->addDecorators(array(array('HtmlTag', array('class' => 'zf-htmltag-submit'))));
  20.  
  21.        $form->addElements(array($login, $password, $submit));
  22.        
  23.        return $form;
  24.    }
  25.    
  26.    function indexAction() {
  27.        $this->view->title = "Twoje konto :: Logowanie";
  28.        
  29.        $form = $this->getForm();
  30.        
  31.        if ($this->_request->isPost()) {
  32.            $formData = $this->_request->getPost();
  33.            if ($form->isValid($formData)) {
  34.                $objDbAdapter = new Zend_Db_Adapter_Pdo_Mysql(array('host' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'zend'));
  35.                $objAuthAdapter = new Zend_Auth_Adapter_DbTable($objDbAdapter, 'users', 'login', 'password', 'MD5(?)');
  36.                $objAuthAdapter->setIdentity($this->_getParam('login'))->setCredential($this->_getParam('password'));
  37.                $objAuth = Zend_Auth::getInstance();
  38.                $objResult = $objAuth->authenticate($objAuthAdapter);
  39.                if ($objResult->isValid()) {
  40.                    $data = $objAuthAdapter->getResultRowObject(null, 'password');
  41.                    $objAuth->getStorage()->write($data);
  42.                    $this->_redirect('/account/');
  43.                } else {
  44.                    $this->view->message = '<p class="zf-errors" style="margin-bottom: 10px;">Logowanie nie powiodło się.</p>';
  45.                }
  46.            }
  47.        }
  48.        
  49.        $this->view->form = $form;
  50.        $this->view->user = Zend_Auth::getInstance()->getIdentity();
  51.    }
  52. ?>


Aha i jeszcze jedno pytanko, bo z tego co wiem, to dzięki temu zend_auth można wypisać różnego rodzaju błędy. W jaki sposób się to tworzy? No bo ja mam tylko else, w którym jest napis, że logowanie nie powiodło się.
Sabistik
  1. <?php
  2. $objResult->getCode();
  3. ?>

Dostajesz odpowiedni kod błędu.
in5ane
Cytat(Sabistik @ 7.07.2009, 09:27:18 ) *
  1. <?php
  2. $objResult->getCode();
  3. ?>

Dostajesz odpowiedni kod błędu.


Dzięki, a ogólnie skrypt dobrze napisany?

Wziąłem się teraz za zend_acl. Utworzyłem sobie kod (przy pomocy manuala):
  1. <?php
  2. require_once 'Zend/Acl.php';
  3. $acl = new Zend_Acl();
  4. require_once 'Zend/Acl/Role.php';
  5.  
  6. $acl->addRole(new Zend_Acl_Role('guest'));
  7. $acl->addRole(new Zend_Acl_Role('user'), 'guest');
  8. $acl->addRole(new Zend_Acl_Role('administrator'));
  9.  
  10. $acl->allow('guest', null, 'index');
  11. $acl->allow('user', null, array('announcements', 'contact'));
  12. $acl->allow('administrator');
  13. ?>


I co ja teraz tak naprawdę mam z nim zrobić? Gdzie go wklepać? Jak sprawdzać role (typ) użytkownika? Proszę o nakierowanie, bo tego w dokumentacji nie było.
in5ane
Cytat(viking @ 8.07.2009, 06:22:29 ) *


No ogólnie przejrzałem i ładnie jest opisane, ale nie zostało uwzględnione w jakich plikach mam to zawrzeć. Ja osobiście myślę, że trzeba to zawrzeć jakoś w bootstraperze, ponieważ on jest (tak jakby) dołączany do każdej podstrony.

W moim skrypcie wszystko wygląda tak:
IndexController (jedna podstrona)
AccountController (logowanie, rejestracja)
AnnouncementsController (wyświetlanie ogłoszeń, wyświetlanie poszczególnego ogłoszenie [podstrona w tej pierwsze podstronie), dodawanie ogłoszeń)
AdminController (jedna podstrona z informacjami typu: bla bla bla, później będę rozbudowywał)
ContactController (jedna podstrona)

Swoje logowanie oczywiście mam w tym Account, i tam mam w indexAction sprawdzanie formularza i logowanie za pomocą Zend_Auth i domyślam się, że tam trzeba jakoś to połączyć z Zend_Acl.
viking
Cytat(in5ane @ 8.07.2009, 10:48:50 ) *
No ogólnie przejrzałem i ładnie jest opisane, ale nie zostało uwzględnione w jakich plikach mam to zawrzeć. Ja osobiście myślę, że trzeba to zawrzeć jakoś w bootstraperze, ponieważ on jest (tak jakby) dołączany do każdej podstrony.

Zastanów się przez chwilę. Jakie jest mapowanie ścieżek dla autoloadera?
I zobacz http://code.google.com/p/zendframeworkstor...anches/chapters
in5ane
No mapowanie ścieżek jest takie (przykład): Jakas_Tam_Sobie_Klasa <-- nazwa klasy i ścieżka, jakas/tam/sobie/klasaClass.php. Ale co mi to daje? Chciałbym się dowiedzieć jak mogę Zend_Acl zintegrować ze swoim systemem logowania.

W końcu wiem, że to (patrz niżej) trzeba umieścić w index.php (bootstraperze):
  1. <?php
  2. $acl = new Zend_Acl();
  3. $acl->add(new Zend_Acl_Resource('index'));
  4. $acl->add(new Zend_Acl_Resource('account'));
  5. $acl->add(new Zend_Acl_Resource('announcements'));
  6. $acl->add(new Zend_Acl_Resource('admin'));
  7. $acl->add(new Zend_Acl_Resource('contact'));
  8. $acl->addRole(new Zend_Acl_Role('guest'));
  9. $acl->addRole(new Zend_Acl_Role('member'), 'guest');
  10. $acl->addRole(new Zend_Acl_Role('admin'), 'member');
  11. $acl->allow('guest', 'index');
  12. $acl->allow('guest', 'contact');
  13. $acl->allow('member', 'account');
  14. $acl->allow('member', 'announcements');
  15. $acl->allow('admin');
  16. ?>


Co dalej muszę zrobić? Jakie pliki i gdzie utworzyć? Proszę o pomoce, nakierowanie - nie gotowce.

Poczytałem jeszcze trochę i już więcej wykombinowałem:

W library dwa pliczki:
  1. <?php
  2. class My_Controller_Helper_Acl {
  3.    public $acl;
  4.    
  5.    public function __construct() {
  6.        $this->acl = new Zend_Acl();
  7.    }
  8.    
  9.    public function setRoles() {
  10.        $this->acl->addRole(new Zend_Acl_Role('guest'));
  11.        $this->acl->addRole(new Zend_Acl_Role('user'));
  12.        $this->acl->addRole(new Zend_Acl_Role('admin'));
  13.    }
  14.    
  15.    public function setResources() {
  16.        $this->acl->add(new Zend_Acl_Resource('index'));
  17.        $this->acl->add(new Zend_Acl_Resource('account'));
  18.        $this->acl->add(new Zend_Acl_Resource('announcements'));
  19.        $this->acl->add(new Zend_Acl_Resource('admin'));
  20.        $this->acl->add(new Zend_Acl_Resource('contact'));
  21.    }
  22.  
  23.    public function setPrivilages() {
  24.        $this->acl->allow('guest', null, 'index');
  25.        $this->acl->allow('user', array('account', 'announcements', 'contact'));
  26.        $this->acl->allow('admin');
  27.    }
  28.    
  29.    public function setAcl() {
  30.        Zend_Registry::set('acl', $this->acl);
  31.    }
  32. }
  33. ?>

oraz
  1. <?php
  2. class My_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract {
  3.    public function preDispatch(Zend_Controller_Request_Abstract $request) {
  4.    
  5.        $application = new Zend_Session_Namespace('myApplication');
  6.        $acl = Zend_Registry::get('acl');
  7.        
  8.        if($application->currentRole == '') {
  9.            $roleName = 'guest'; // jezeli w sesji obecna role (typ) uzytkownika jest pusty, zostanie ustawione guest
  10.        } else {
  11.            $roleName = $application->currentRole; // w przeciwnym wypadku zapisujemy w zmiennej $roleName nasza role (typ) uzytkownika
  12.        }
  13.        
  14.        $privilageName = $application->loggedUser;
  15.        if(!$acl->isAllowed($roleName, null, $privilageName)) {
  16.            // cos tam, nie wejdziesz tutaj, bla bla...
  17.        }
  18.  
  19.    }
  20. }
  21. ?>


i w bootstraper (index.php):
  1. <?php
  2. // acl
  3. $helper= new My_Controller_Helper_Acl();
  4. $helper->setRoles();
  5. $helper->setResources();
  6. $helper->setPrivilages();
  7. $helper->setAcl();
  8. $frontController->registerPlugin(new My_Controller_Plugin_Acl());
  9. ?>


No i to ani nie popsuło strony, ani nie działa. Pewnie trzeba jakoś do tego acl wysłać role (typ) użytkownika (czy to użytkownik, czy to admin).


@edit: poprawiłem ten drugi plik Acl.php, starałem się zrobić, żeby dostawał w sesji role i nazwę, no ale nadal coś nie śmiga mi to. Może teraz mnie ktoś nakieruje?
Aha i dodałem też w logowaniu w kontrolerze:
  1. <?php
  2. protected $_application; // przed funkcjami
  3.  
  4.  
  5. $this->view->baseUrl = $this->_request->getBaseUrl(); // w init
  6. $this->_application = new Zend_Session_Namespace('myApplication'); // w init
  7.  
  8.  
  9. $this->_application->currentRole = $this->user->role; // w indexAction, jak juz sie zaloguje
  10. $this->_application->loggedUser = $this->user->login; // w indexAction, jak juz sie zaloguje
  11. ?>


No i i tak po każdej stronie można latać jak się chce ;/
omeck
Cytat(in5ane @ 8.07.2009, 19:51:24 ) *
  1. <?php
  2.        
  3.        $privilageName = $application->loggedUser;
  4.        if(!$acl->isAllowed($roleName, null, $privilageName)) {
  5.            // cos tam, nie wejdziesz tutaj, bla bla...
  6.        }
  7.  
  8.    }
  9. }
  10. ?>


Dlaczego $privilegeName wyciągasz z sesji? To powinien być zasób (u Ciebie index, account itd.). Możesz wyciągnąć np. nazwę kontrolera z request object i wtedy porównywać.
in5ane
Do końca nie wiem, jak ma działać ta instrukcja warunkowa (wiem, że musi zabronić danemu użytkownikowi dostępu do podstrony), była ona zawarta w kilku tutorialach, które czytałem (tyle, że w każdym trochę inna).
omeck
Jeśli korzystasz z MVC, to do isAllowed przekaż kolejno parametry: rolę i zasób (w swoim systemie chyba nie chcesz sprawdzać bardziej szczegółowego dostępu np. do akcji, ale nie wiem :-))
U Ciebie w kodzie rolę chyba dobrze wyciągasz - z sesji użytkownika (zakładając, że ją dobrze przypisujesz winksmiley.jpg). W takim razie należy sprawdzić, czy dana rola ma dostęp do zasobu. Zasoby zdefiniowałeś chyba w index.php (Zend_Acl_Resource) oraz potem przypisałeś role do zasobów (metoda allow). Czy zasobami mają być nazwy kontrolerów? Jeśli tak, to coś takiego może Ci zadziałać:

  1. <?php
  2. $resource = $request->getParam('controller');
  3.  
  4. if(!$acl->isAllowed($roleName, $resource)) {
  5.           // cos tam, nie wejdziesz tutaj, bla bla...
  6. }
  7. ?>


pisane z palca, nie daje 100% gwarancji ;-)

Metoda z 3 argumentami świetnie nadaje się np. do sprawdzania dostępu jakiejś roli do konkretnej akcji konkretnego kontrolera
in5ane
Dzięki, no ale nie blokuje nic ;/

Tzn. zawsze IF przejdzie bez niczego i wyświetli z niego treść itp.. (czyli to bla bla...) i każda podstrona jest dostępna dla gościa. Możliwe, że z tymi danymi w sesji jest problem.
omeck
Cytat(in5ane @ 8.07.2009, 23:13:39 ) *
Dzięki, no ale nie blokuje nic ;/

Tzn. zawsze IF przejdzie bez niczego i wyświetli z niego treść itp.. (czyli to bla bla...) i każda podstrona jest dostępna dla gościa. Możliwe, że z tymi danymi w sesji jest problem.


Ale wchodzi Ci do if'a? Czy nigdy? Co w ogóle masz w if? Jeśli wchodzi, to musisz wewnątrz np. zrobić przekierowanie do jakiejś akcji logowania
in5ane
No wchodzi mi do IF, dodałem sobie tam dla testu echo 'asd'; i zawsze wyświetla (na każdej podstronie). Ale dodałem też echo $application->currentRole; i nie wyświetla tego, więc chyba będzie jakiś problem z sesjami.
omeck
Czy w bootstrapie dałeś:
  1. <?php
  2. Zend_Session::start();
  3. ?>


questionmark.gif

Aha, w pluginie powinieneś odczytywać wartość sesji, a nie ją tworzyć ;-)
in5ane
Tak, dałem. Zobaczyłem też, jak na sztywno dałem w $roleName guest albo admin, to nadal ten IF cały czas działał. Najpierw trzeba coś zrobić z tym IF'em, później z sesjami (bo na razie w $roleName mogę na sztywno wpisywać).
omeck
Cytat(in5ane @ 8.07.2009, 23:27:12 ) *
Tak, dałem. Zobaczyłem też, jak na sztywno dałem w $roleName guest albo admin, to nadal ten IF cały czas działał. Najpierw trzeba coś zrobić z tym IF'em, później z sesjami (bo na razie w $roleName mogę na sztywno wpisywać).


No dobra, ale:
  1. <?php
  2. $this->acl->allow('guest', null, 'index');
  3.       $this->acl->allow('user', array('account', 'announcements', 'contact'));
  4.       $this->acl->allow('admin');
  5. ?>


Gość ma dostęp wyłącznie do domyslnego modułu oraz zasobu index - przy każdym inny zasobie będzie Ci wchodził do If. Admin z kolei nie ma żadnych uprawnień...
in5ane
No dobra, wiem o co Ci chodziło, doszedłem do tego, że jest w sumie dobrze, poza sesjami, mój kod teraz wygląda tak:

  1. <?php
  2. class My_Controller_Helper_Acl {
  3.    public $acl;
  4.    
  5.    public function __construct() {
  6.        $this->acl = new Zend_Acl();
  7.    }
  8.    
  9.    public function setRoles() {
  10.        $this->acl->addRole(new Zend_Acl_Role('guest'));
  11.        $this->acl->addRole(new Zend_Acl_Role('user'), 'guest');
  12.        $this->acl->addRole(new Zend_Acl_Role('admin'), 'user');
  13.    }
  14.    
  15.    public function setResources() {
  16.        $this->acl->add(new Zend_Acl_Resource('index'));
  17.        $this->acl->add(new Zend_Acl_Resource('account'));
  18.        $this->acl->add(new Zend_Acl_Resource('announcements'));
  19.        $this->acl->add(new Zend_Acl_Resource('admin'));
  20.        $this->acl->add(new Zend_Acl_Resource('contact'));
  21.    }
  22.  
  23.    public function setPrivilages() {
  24.        $this->acl->allow('guest', 'index');
  25.        $this->acl->allow('user', array('account', 'announcements', 'contact'));
  26.        $this->acl->allow('admin', 'admin');
  27.    }
  28.    
  29.    public function setAcl() {
  30.        Zend_Registry::set('acl', $this->acl);
  31.    }
  32. }
  33. ?>

Oczywiście muszę jeszcze te uprawnienia do podstron ustawić (do jakich podstron).

  1. <?php
  2. class My_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract {
  3.    public function preDispatch(Zend_Controller_Request_Abstract $request) {
  4.    
  5.        $application = new Zend_Session_Namespace('myApplication');        
  6.        if('user' == '') {
  7.            $roleName = 'guest'; // jezeli w sesji obecna role (typ) uzytkownika jest pusty, zostanie ustawione guest
  8.        } else {
  9.            $roleName = 'user'; // w przeciwnym wypadku zapisujemy w zmiennej $roleName nasza role (typ) uzytkownika
  10.        }
  11.        
  12.        $acl = Zend_Registry::get('acl');
  13.        $resource = $request->getParam('controller');
  14.        if(!$acl->isAllowed($roleName, $resource)) {
  15.            // cos tam, nie wejdziesz tutaj, bla bla...
  16.            echo 'as';
  17.        }
  18.        
  19.    }
  20. }
  21. ?>

W tym ustawiłem na sztywno w tym IF'ie 'user' == '' oraz $roleName = 'user';.

I to echo 'as'; przy tych parametrach user wyświetla mi tylko w podstronie admin, więc ogólnie to działa. Ale trzeba coś z tymi sesjami zrobić. Prawdopodobnie jest problem z ich wysłaniem.


@edit: poradziłem sobie, dziękuje wszystkim za zainteresowanie.

@edit2: chciałbym się jeszcze dowiedzieć jak zrobić, żeby np. announcements było dostępne dla guest, ale announcements/add już tylko dla user?
omeck
Możesz swój kod rozszerzyć w ten sposób (zakładam, że zasoby to nazwy kontrolerów?)
  1. <?php
  2.    public function setPrivilages() {
  3.        $this->acl->allow('guest', 'kontroler1', array('akcja1', 'akcja2'));
  4.        $this->acl->allow('guest', 'kontroler2', array('akcja1'));
  5.        $this->acl->allow('user', 'kontroler1', array('account', 'announcements', 'contact'));
  6.        $this->acl->allow('admin', 'admin');
  7.    }
  8. ?>


Więcej kodu, ale uzyskasz bardziej szczegółowa listę dostępu. Definiuj więc pozwolenia dla jakieś roli i zasobu, a w 3 parametrze podawaj tablicę akcji do których dana rola będzie miała dostęp.

Wówczas musisz jeszcze zmienić plugin... muszę zaraz wychodzić, więc nie mam czasu na wyjaśnienie - zobacz mój, może Cię oświeci ;-) Smacznego!

  1. <?php
  2. /**
  3.  * Plugin kontrolera sprawdzający autoryzację i autentykację
  4.  * @author omeck
  5.  * @version $Id$
  6.  */
  7. class Acl_Plugin extends Zend_Controller_Plugin_Abstract
  8. {
  9.    /**
  10.      * Dostęp do obiektu uwierzytelniania
  11.      * @var Zend_Auth
  12.      */
  13.    protected $_auth = null;
  14.    
  15.    /**
  16.      * Dostęp do ACL
  17.      * @var Zend_Acl
  18.      */
  19.    protected $_acl = null;
  20.  
  21.    public function __construct(Zend_Auth $auth, Zend_Acl $acl)
  22.    {
  23.        $this->_auth = $auth;
  24.        $this->_acl = $acl;
  25.    }
  26.    
  27.    public function preDispatch(Zend_Controller_Request_Abstract $request)
  28.    {
  29.        // sprawdz, czy user jest zalogowany...
  30.        if ($this->_auth->hasIdentity()) {
  31.            // zalogowany, pobierz nazwę roli z obiektu Auth
  32.            $role = $this->_auth->getIdentity()->role;
  33.        } else {
  34.            // niezalogowany, daj mu uprawnienia gościa
  35.            $role = 'guest';
  36.        }
  37.      
  38.        // okreslenie bierzacego modułu
  39.        // będzie to albo null (czyli default), albo admin
  40.        $resource = $request->module;
  41.        
  42.        if ($resource == 'admin') {
  43.            // jesli modulem, do którego użytkownik chce się dostac jest admin,
  44.            // wtedy sprawdzany jest dostęp po module i roli użytkownika,
  45.            // czyli rola i moduł muszą nazwyac się 'admin'
  46.            $resource = 'admin';
  47.            $assert = null;            
  48.        } else {
  49.            // wywołanie na stronie publicznej w module default
  50.            // tutaj sprawdzany jest kontroler i akcja
  51.            $resource = $request->getParam('controller');
  52.            $assert = $request->getParam('action');
  53.        }
  54.        
  55.        // sprawdź dostęp przez ACL
  56.        if (!$this->_acl->isAllowed($role, $resource, $assert)) {
  57.            if ($this->_auth->hasIdentity()) {
  58.                // zalogowany, dostęp zabroniony, przekieruj na index
  59.                $request->setModuleName('default');
  60.                $request->setControllerName('index');
  61.                $request->setActionName('index');
  62.            } else {
  63.                // nie zalogowany, przekieruj do formularza logowania
  64.                $request->setModuleName('default');
  65.                $request->setControllerName('login');
  66.                $request->setActionName('index');
  67.            }
  68.        }
  69.    }
  70. }
  71. ?>
in5ane
Hehe, dzięki. Ale właśnie w tym samym czasie udało mi się to samemu osiągnąć. Ale dzięki za pomoc ;-)


@edit:
Żeby nie tworzyć nowego tematu. Chciałbym się dowiedzieć czy to moje obecne logowanie (kod niżej) jest dobrze napisane i czy nie jest podatne na włamania (w szczególności sql incjection). Z góry dziękuję za zerknięcie w kod.

  1. <?php
  2. function getForm() {
  3.        $form = new Zend_Form();
  4.        $form->setMethod('post');
  5.  
  6.        $login = $form->createElement('text', 'login', array('label' => 'Login'));
  7.        $login->setRequired(true)
  8.                ->addValidator('NotEmpty', true, array('messages' => array('isEmpty' => 'Nie wpisałeś/aś loginu.')))
  9.                ->addDecorators(array(array('HtmlTag', array('class' => 'zf-htmltag')), array('Label', array('class' => 'zf-label')), array('Errors', array('class' => 'zf-errors'))));
  10.  
  11.        $password = $form->createElement('password', 'password', array('label' => 'Hasło'));
  12.        $password->setRequired(true)
  13.                ->addValidator('NotEmpty', true, array('messages' => array('isEmpty' => 'Nie wpisałeś/aś hasła.')))
  14.                ->addDecorators(array(array('Label', array('class' => 'zf-label')), array('HtmlTag', array('class' => 'zf-htmltag')), array('Errors', array('class' => 'zf-errors'))));
  15.  
  16.        $submit = $form->createElement('submit', 'log', array('label' => 'Zaloguj się'));
  17.        $submit->addDecorators(array(array('HtmlTag', array('class' => 'zf-htmltag-submit'))));
  18.  
  19.        $form->addElements(array($login, $password, $submit));
  20.        
  21.        return $form;
  22.    }
  23.    
  24.    function indexAction() {
  25.        $this->view->title = "Twoje konto";
  26.    
  27.        $form = $this->getForm();
  28.    
  29.        if ($this->_request->isPost()) {
  30.            $formData = $this->_request->getPost();
  31.            if ($form->isValid($formData)) {
  32.                $dbAdapter = Zend_Registry::get('dbAdapter');
  33.                $objAuthAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter, 'users', 'login', 'password', 'MD5(?)');
  34.                $objAuthAdapter->setIdentity($this->_getParam('login'))->setCredential($this->_getParam('password'));
  35.                $objAuth = Zend_Auth::getInstance();
  36.                $objResult = $objAuth->authenticate($objAuthAdapter);
  37.                if ($objResult->isValid()) {
  38.                    $data = $objAuthAdapter->getResultRowObject(null, 'password');                    
  39.                    $objAuth->getStorage()->write($data);                    
  40.                    $this->_application->currentRole = Zend_Auth::getInstance()->getIdentity()->role;
  41.                    $this->_redirect('/account');
  42.                } else {
  43.                    $this->view->message = '<p class="zf-errors" style="margin-bottom: 10px;">Błędna nazwa użytkownika, albo hasło.</p>';
  44.                }
  45.            }
  46.        }
  47.        
  48.        $this->view->form = $form;
  49.        $this->view->user = Zend_Auth::getInstance()->getIdentity();
  50.    }
  51.  
  52.    function logoutAction() {
  53.        Zend_Auth::getInstance()->clearIdentity();
  54.        $this->_application->currentRole = 'guest';
  55.        $this->_redirect('/account');
  56.    }
  57. ?>
omeck
Raczej jest ok, jeśli sam bezpośrednio nie wywołujesz zapytań z nieprzefiltrowanymi danymi to, klasy z "pakietu" Zend_Db w miarę je filtrują.

BTW
nie byłoby Ci wygodniej (biorąc pod uwagę dalszy rozwój aplikacji przenieść inicjowanie Zend_Auth, adaptera bazy, a formularza do osobnej klasy? Sory, że się czepiam ;-)
in5ane
Cytat(omeck @ 10.07.2009, 10:11:53 ) *
Raczej jest ok, jeśli sam bezpośrednio nie wywołujesz zapytań z nieprzefiltrowanymi danymi to, klasy z "pakietu" Zend_Db w miarę je filtrują.

BTW
nie byłoby Ci wygodniej (biorąc pod uwagę dalszy rozwój aplikacji przenieść inicjowanie Zend_Auth, adaptera bazy, a formularza do osobnej klasy? Sory, że się czepiam ;-)


No spoko, że mi podpowiadasz. Adapter bazy już przeniosłem do bootstrapera. Inicjowanie Zend_Auth gdzie przenieść? A formularz, po co do osobnej klasy (nie wiem dlaczego, skoro to jest formularz tylko logowania)?
omeck
Cytat(in5ane @ 10.07.2009, 14:23:52 ) *
Inicjowanie Zend_Auth gdzie przenieść? A formularz, po co do osobnej klasy (nie wiem dlaczego, skoro to jest formularz tylko logowania)?


W sumie niczego nie musisz przenosić, ale jeśli będziesz rozbudowywał aplikację, to wygodniej Ci będzie rozdzielić kod ;-)
Ja mam np. Zend_Auth zainicjowany w bootstrapie:
  1. <?php
  2. public static function setupAcl()
  3. {
  4.        $auth = Zend_Auth::getInstance();
  5.        $acl = new Acl_Access();
  6.        // dwie poniższe linijki nie sa teraz potrzebne, ale może kiedyś się przydadzą ;-)
  7.        //self::$frontController->setParam('auth', $auth);
  8.        //self::$frontController->setParam('acl', $acl);
  9.        self::$frontController->registerPlugin(new Acl_Plugin($auth, $acl));
  10.        
  11. }
  12. ?>


Pluginek wcześniej wkleiłem. Moja klasa Acl_Access ustawia po prostu uprawnienia: role -> (kontroler, akcja)

Dodatkowo stosuję kontroler, który zajmuje się wyłącznie logowaniem (ustawienie adaptera i proces logowania).

Co do formularzy to każdy (prawie każdy) trzymam w osobnym pliku (klasie) dziedziczącej w Zend_Form, ale w sumie u Ciebie jak masz jeden form to może nie będzie trzeba tego robić.

Jest na prawdę sporo rozwiązań - masz pełną swobodę, za co niezwykle cenię Zenda guitar.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.