Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: Athlan, dodany: 28.12.2008 15:35, tagi: php, internet

Projektując serwisy zaczynam ostrożnie podchodzić do usability. Temat jest bardzo wrażliwy, każdy webmaster to inne zdanie. Dziś chciałbym przedstawić problem logowania do serwisu. Oprócz hasła, przy logowaniu używamy:

  • standardowo nazwy użytkownika,
  • w niektórych serwisach adresu email, rzadziej spotykane zjawisko.

W trosce o użytkowników w kilku moich serwisach zastosowałem możliwość logowania się na adres email lub nazwę użytkownika. Wszystko po to, aby ułatwić dostęp do ukrytej części witryny, aby nikt nie “zwątpił” bo nazwy użytkownika, lub adresu email, który podał przy zakładaniu profilu. Sam używam w sieci kilku adresów email oraz kilku prefixów i suffixów do nicka Athlan. Mam problem z zalogowaniem, gdy danie nie pasują, a potrzebuję dostęp tylko na chwilę.

Przygotujmy zatem tok myślenia programu, który pobierze dane, w zależności od tego, jakie dane podał użytkownik. Pomijam walidację hasła etc:

  1. Wykrycie, czy nick jest adresem email.
  2. Jeżeli tak, pobierz dane użytkownika po polu user_mail i zapisz je do zmiennej $aUser.
  3. Jeżeli nie, pobierz dane identyfikując rekord po kluczu user_name i zapisz pobrane dane do zmiennej $aUser.

Jak możemy zauważyć, w obu przypadkach dane zapisujemy do tej samej zmiennej $aUser, więc możemy je dalej tak samo wykorzystywać. Różni się tylko pobieranie, dlateg nie trzeba w żadnym wypadku powielać kodu.

Jak słusznie zauważył devnull, należy wykluczyć możliwość użycia znaku małpy w loginie przy rejestracji użytkownika. Wyjaśnienie znajdziecie w komentarzach.

Dla programisty nie jest wiele pracy, a warto ułatwić dostęp użytkownikowi do serwisu. Usability na pierwszym miejscu ;-)

Autor wpisu: Diabl0, dodany: 28.12.2008 01:01, tagi: php, eclipse

var-autocomplete-example_0Podpowiadanie typu zmiennej za pomocą @var jest bardzo użyteczne, jednak wpisywanie tego to droga przez mękę. Niestety twórcy PDT/ZS nie pomyśleli o żadnych mechanizmach podpowiedzi zmiennych czy klas, tak że zwykle kończy się to metodą copy/paste albo żmudnym literowaniem:

/* @var $controller Zend_Controller_Front */

Przypadkiem jednak trafiłem na blog Alex @ Net na którym podpowiada on pewną sztuczkę. Poniżej tłumaczenie na polski

Na szczęście na ratunek przychodzą “szablony” dzięki którym możliwe jest uzyskanie podpowiedzi:

var-autocomplete-example_0

Aby dodać odpowiedni szablon otwórz menu Window, wybierz Preferences i przejdź do sekcji PHP/Templates. Następnie kliknij przycisk “New…” i w oknie wypełnij pola według poniższego schematu:

var-autocomplete-settings_0

Pole Pattern przepisz jak najdokładniej. ZS proponuje mi w miejsce wartości ${dollar} wartość $$ - nie słuchaj ZS ;)

Po tym zabiegu już w kodzie wpisz sobie “var” i wciśnij Ctrl+Space. Wybierz “var - Variable type hint” z listy i kontunuuj wpisując bądź wybierając nazwę zmiennej oraz klasy, jak zaprezentowano na filmiku poniżej:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Diabl0, dodany: 27.12.2008 20:54, tagi: php

Axure

Axure

Dzisiaj chciałbym poruszyć kwestię projektowania w małych i pojedyńczych zespołach. Od razu zaznaczę że nie jestem z wykształcenia informatykiem - wszystkiego uczyłem się sam i do wszystkiego sam dochodziłem, tak więc teoretyków i uczelnianych purystów proszę o nie zabieranie głosu. Poniżej zaprezentuję bowiem podejście które nie zawsze jest zgodne z “oficjalnymi  szkołami”, ale za to sprawdzone w boju i praktyce.

Zacznę od pierwszego etapu “projektowania” czyli zbierania informacji “co chce klient”. Co prawda w moim przypadku “klient” jest zarazem moim szefem, ale nie zmienia to faktu że nie jest on programistą ani informatykiem i należy do niego podchodzić tak jak do każdego innego niedokońca zdecydowanego i wiedzącego co chce klienta.

Tak więc w moim przypadku pierwszy etap to zbieranie wszystkich wolnych myśli, pomysłów, oderwanych od siebie pragnień i wizji oraz zapisywanie ich i późniejsza próba uporządkowania. Doskonałym narzędziem wspomagającym ten proces są diagramy burzy mózgów.

Burza mózgówOsobiście wykorzystuję do tego celu Microsoft Visio. Zapewne istnieją do tego lepsze, bardziej rozbudowane lub wygodniejsze narzędzia, ale… to działa, też jest wygodne,  i mam je pod ręką ;) W każdej chwili mogę szybko otworzyć projekt i dopisywać kolejne luźne myśli oraz pomysły, a później uporządkować je w chierarchię przypominającą drzewo. W moim przypadku taka burza mózgów tworzona jest od pierwszych rozmów o projekcie do czasu zakończenia drugiej fazy jakim jest przygotowanie prototypu - projektu funkcjonalnego.

Do przygotowania prototypu wykorzystuję komercyjne narzędzie jakim jest Axure. Pozwala on na budowanie prostych witryn których jedynym celem jest zobrazowanie jak projektanci i programiści widzą to co zostało zanotowane w burzy mózgów. Prototyp taki przypomina prosty serwis, ale jest statyczny i pozbawiony elementów layoutu. Najważniejsze w nim jest przedstawienie wszystkich podstron, tabel, form, przycisków, linków i zależności typu - dodając produkt klikam tutaj, wpisuję to i to, klikam “dalej” gdzie wpisuję tamto i tamto, itp.

screen_003Dobrze wykonany rozbudowany prototyp daje klientowi namiastkę działania docelowego serwisu, pozwala nam zorientować się czy to co my widzimy to jest to co klient chce, daje możliwość wstępnego rozplanowania serwisu. Dzięki prototypowi można łatwo stworzyć odpowiednie procedury i procesy (dodanie produktu do magazynu, proces rejestracji itp), a także  odnaleźć i wyeliminować wszelkie niejasności oraz problemy z funkcjonalnością wynikające z różnej wiedzy informatyków i późniejszych użytkowników końcowych (których wiedza informatyczna często kończy się na klikaniu największych przycisków). Prototyp taki daje także możliwość szybkich poprawek i uwzględniania uwag klienta zanim jeszcze siądzie się do edytora.

Co również ciekawe, dopracowany i zaakceptowany prototyp pozwala później na łatwe odwzorowanie projektu na wzorzec MVC - dość wyraźnie widać podział na kontrolery i akcje.

Polecam obejrzenie sobie “wycieczki” prezentującej możliwości i zalety Axure - http://axure.com/tour.aspx czy przykładowego prototypu.

Kolejny 3 etap projektowania do przygotowanie bazy danych. Mając informacje z burzy mózgów oraz “podgląd” jak to będzie wyglądało w gotowym serwisie, dość łatwo możemy wywnioskować jakie informacje będziemy przechowywali, i jak będziemy na nich pracować. Ale to już temat który dość często i szeroko jest poruszany w internecie, i łatwo znaleźć odpowiednie informacje.

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Athlan, dodany: 26.12.2008 20:35, tagi: php, internet

Dla niektórych wygasanie sesji jest zabezpieczeniem (banki, etc.). Realizując jeden z projektów oczekiwałem od systemu tego, aby użytkownik nigdy nie gubił sesji, gdy ma otwarte okno w przeglądarce. Dlaczego? Może dodaje posta, być może uzupełnia dość obszerny tekst na stronie. Gdy klika zapisz, przerzuca go do strony logowania, a cały tekst zniknął za sprawą tego, że jego przeglądarka nie zapisuje wartości pól formularza. Skąd to znamy.

Jak użytkownik gubi sesję?

  1. Jego ciastko wygasa, więc serwer nie może go zidentyfikować z sesją.
  2. Po jakimś czasie, choćby odtworzył ciastko, plik sesji znika z naszego serwera (garbage collection).

Rozwiązania:

  1. Wydłużenie czasu wygasania ciastka i sesji.
  2. Odświeżenie strony w interwale mniejszym, niż wynosi czas wygasania sesji i ciastka.

Rozmyślając nad podtrzymaniem sesji, próbowałem znaleźć wszystkie metody oraz wybrać najlepszą. Wszystkie sprowadzają się do “odświeżenia” strony lub jej fragmentu tak, aby nasz silnik wykonał tylko potrzebne session_start(); czyli podtrzymanie aktywności sesji. Jest kilka mniej lub bardziej zadowalających sposobów:

  1. Odświeżenie całej strony. To może spowodować, że dane wprowadzane przez użytkownika w formularzu zostaną utracone. Ponad to, jeżeli użytkownik czyta newsy, denerwującym może być fakt, że lista nagle zostanie przescrollowana do góry (prócz opery).
  2. Wysłanie requestu ajax w tle. Minusem jest to, że trzeba używać biblioteki ajax lub pisać dodatkowy kod javascriptu. Jeżeli ktoś na stronie używa jakiegoś ajaxa - co za różnica. Poza tym same plusy.
  3. Odświeżanie ukrytej ramki iframe lub elementu frameset. Minusów usablity prawie brak. Brak potrzeby instalacji javascriptów i ajaxa. Odświeżacz powinien wysłać nagłówek Refresh lub odpowiedni metatag.

Sposób 3 wydaje mi się najlepszy. Można go ulepszyć w ten sposób, aby ramka nie wysyłała żądania zaraz po załadowaniu strony. Powodowałoby to podwójne requesty do serwera.

Zapewne znajdą się osoby, które powiedzą: a co z użytkownikami, którzy mają wyłączone ramki, lub ich przeglądarki w ogóle ich nie obsługują. Zapytam wówczas: a co z użytkownikami, którzy nie akceptują cisteczek (wówczas sesje nie są dla nich użyteczne, chyba, że użyjemy przesłyki jej identyfikatora w adresie url). Dopytam również: a co z użytkownikami, którzy mają wyłączony Javascript? Patologiczne przepadki się po prostu pomija ;)

Autor wpisu: Diabl0, dodany: 26.12.2008 01:42, tagi: php

Większość użytkowników Zend Studio narzeka na powolne działanie debuggera w Zend Studio for Eclipse. Co prawda w 6.1 znacznie poprawili jego działanie, ale nadal pozostaje sporo do życzenia. Przed chwilą przypadkiem dokopałem się do ciekawej dyskusji na grupie poświęconej ZS, i wypowiedzi jednego z developerów. Cytuję z kilkoma skrótami i bez tłumaczenia.

Regarding the slow debugging – until we release an update – please approach support and you will get a patch to fix the slow debugging issue.

Has been tested and verified here and with customers.

Gadi Goldbarg, Development Tools , QA Team Leader , Zend.

I po kilku postach mocno krytykujących zachowanie firmy Zend i podejście do klienta oraz problemu kolejna odpowiedź:

You guys are correct , we should have posted it here and let you all know - please find attached a patch for slow debugging (when debug starts from toolbar).

Please replace the file under - C:\Program Files\Zend\Zend Studio for Eclipse - 6.1.0\plugins\ org.eclipse. php.debug. core_1.0. 5.v20080907. jar with attached one.

Gadi Goldbarg, Development Tools , QA Team Leader , Zend.

Plik:  orgeclipsephpdebugcore_105v20080907

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Diabl0, dodany: 23.12.2008 17:15, tagi: zend_framework

KalendarzBardzo często tworząc różnego rodzaju formularze korzystamy z pól do wprowadzania daty. Miłym uzupełnieniem dla użytkowników takiego pola jest dodanie kalendarza z którego mogą sobie oni wybrać datę. Jednym z najbardziej znanych narzędzi tego typu jest The Coolest DHTML Calendar. A jako zwolennik Zend_Form, zaraz pokażę wam jak ułatwić sobie życie i stworzyć Zend_Form_Element do szybkiego i prostego podłączania takiego kalendarza do formy.

Dotychczas chcąc dać użytkownikom możliwość wyboru daty z kalendarza używałem albo Dojo i jego dijit.form.DateTextBox (rozwiązanie mocno ograniczone pod względem możliwości), albo tworzyłem w formie zwykły element text i w widoku formy dodawałem kod odpowiedzialny z a DHTML Calendar. Aż ostatecznie dzisiaj rano stwierdziłem że można to rozwiązać znacznie prościej i wygodniej pisząc własny element Zend_Form_Element. I poniżej znajdziecie tego wstępne rezultaty.

Zacznijmy od elementu formy:

/**
 * calendar form element
 *
 * @uses Mao_View_Helper_FormCalendar
 */
class Mao_Form_Element_Calendar extends Zend_Form_Element_Xhtml
{
    /**
     * Default form view helper to use for rendering
     * @var string
     */
    public $helper = 'formCalendar';

}

Klasa ta jest kalką Zend_Form_Element_Text i jej głównym przeznaczeniem jest określenie helpera widoku - formCalendar gdzie odbywa się większość “magii

/**
 * Helper to generate a "calendar" element
 *
 * @todo uporządkować
 * @todo obsługa parametrów
 */
class Mao_View_Helper_FormCalendar extends Zend_View_Helper_FormElement
{
    /**
     * Generates a 'text' element.
     *
     * @access public
     *
     * @param string|array $name If a string, the element name.  If an
     * array, all other parameters are ignored, and the array elements
     * are used in place of added parameters.
     *
     * @param mixed $value The element value.
     *
     * @param array $attribs Attributes for the element tag.
     *
     * @return string The element XHTML.
     */
    public function formCalendar($name, $value = null, $attribs = null)
    {
        $info = $this->_getInfo($name, $value, $attribs);
        extract($info); // name, value, attribs, options, listsep, disable

        // build the element
        $disabled = '';
        if ($disable) {
            // disabled
            $disabled = ' disabled="disabled"';
        }

        // XHTML or HTML end tag?
        $endTag = ' />';
        if (($this->view instanceof Zend_View_Abstract) && !$this->view->doctype()->isXhtml()) {
            $endTag= '>';
        }

        $xhtml = '<input type="text"'
                . ' name="' . $this->view->escape($name) . '"'
                . ' id="' . $this->view->escape($id) . '"'
                . ' value="' . $this->view->escape($value) . '"'
                . $disabled
                . $this->_htmlAttribs($attribs)
                . $endTag;

        if ( !$disable) {

            $this->view->headLink ()->appendStylesheet('http://cdn.local.ss/js/calendar/calendar-system.css');
            $this->view->headScript()
                ->appendFile ( 'http://cdn.local.ss/js/calendar/calendar.js', 'text/javascript')
                ->appendFile ( 'http://cdn.local.ss/js/calendar/lang/calendar-en.js', 'text/javascript')
                ->appendFile ( 'http://cdn.gazeta.ie/js/calendar/calendar-setup.js', 'text/javascript');

            $xhtml .= '<button' . ' id="' . $this->view->escape($id) . '_trigger"' . '><img src="http://cdn.local.ss/images/crystal/16x16/actions/1day.png"></button>';

            $xhtml .= '
            <script type="text/javascript">
                //<![CDATA[
    			  Calendar.setup(
    			    {
    			      inputField  : "' . $this->view->escape($id) . '",         // ID of the input field
    			      ifFormat    : "%Y-%m-%d",    // the date format
    			      button      : "' . $this->view->escape($id) . '_trigger"       // ID of the button
    			    }
    			  );
    		    //]]>
        	</script>
    		';
        }

        return $xhtml;
    }
}

Początek jest żywcem przekopiowany z dowolnego Zend_View_Helper_Form*, jednak końcówka zawiera już sam miodzik

  1. po sprawdzeniu czy element nie jest wyłączony ( $disabled ) za pomocą helperów headLink i headScript dodajemy linki do skryptów JS i CSS.  W powyższym przykładzie odpowiednie pliki znajdują się na firmowym CDNie i są wpisane na stałe. W ostatecznym kodzie wypadało by użyć helpera baseUrl.
  2. do pola <input type=”text” (zawartego w zmiennej $xhtml) dodajemy element button który będzie naszym triggerem (id = $id . ‘_trigger’)
  3. Dodawany jest kawałek kodu JS inicializujący DHTML dla triggera

I… to na razie wszystko, gdyż moja doza zapału w te święta chwilowo się wyczerpała ;) Oczywiście, cały zaprezentowany powyżej kod to tylko szybka wstępna wersja (szkic) który należy jeszcze odpowiednio rozbudować (np. możliwość ustalania formatu daty z poziomu formy, własny kod triggera itp), ale po świętach kogoś do niego posadzę i może kiedyś zaprezentuję bardziej rozbudowaną i elastyczną wersję. W ostateczności powinna to być także dobra podstawa do własnych eksperymentów jako prosty i działający przykład własnego elementu.

Related posts

Autor wpisu: Athlan, dodany: 22.12.2008 19:50, tagi: php

Przeglądając forum.php.pl często widziałem, jak użytkownicy przechowują hasła w swoich bazach danych. Najczęściej używają funkcji hashujących md5, sha1 i sha2. Wszystko wygląda bardzo dobrze, hasła są przechowywanie bezpiecznie. No właśnie… na ile bezpiecznie.

Nie będę tutaj rozwodził się nad zabezpieczeniem baz danych, w których owa baza haseł się znajduje, ale nad samym zahashowanym ciągu. Wszyscy doskonale wiemy, że istnieją bazy md5 (sha1, sha2 również).

Przezorny zawsze ubezpieczony. Wiadomo, że nigdy nic nie wiadomo.

Pokażę, jak dodatkowo zabezpieczyć nasze hasła. Będą przechowywane w tej samej bazie danych, używając tych samych metod hashowania, a jednak szansa na “złamanie” hasła (wyszukania w bazie) będzie niemożliwa. Posłużymy się ciągiem znaków zwanym przez programistów solą (salt). Przykład implementacji możemy znaleźć w forum IPB, natomiast phpBB pozbawione jest tego fjuczuru ficzera. Cała sprawa sprowadza się do wygenerowania dowolnego kawałka ciągu znaków i doklejenia go do hasła. Sól potrzebna nam będzie również przy porównaniu hasła, więc trzeba ją zapisać w bazie danych obok hasła.

Poniżej zamieszczam przykładową klasę, która obsługuje solenie haseł. Doklejanie soli może być napisane w dowolny sposób, zależy to od Waszej wyobraźni. Ja dodatkowo dodałem element “losowy” w postaci doklejenia do soli wyniku działania funkcji microtime().

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.