10/2013 (17)
www•programistamag•pl
Cena 9.90 zł (w tym VAT 23%)
Index: 285358
Certfikaty SSLThere is no app
Arduino a sprawa wyświetlaczy • ASP.NET SignalR • Budowanie wiedzy w zespole. Główne błędy i strategie
OpenGL 2D
Jak one działają i jak to za-
implementować w Javie
Koncepty stojące za filo-
zofią platformy Android
Programowanie grafiki:
o shaderach i teksturach
Twitter Bootstrap
Co nowego w wersji 3
4 / 10 . 2013 . (17) /
REDAKCJA/EDYTORIAL
Nowe wydanie Programisty po raz siedemnasty gości już na Waszych
półkach i czytnikach e-booków i ciągle nie brakuje w naszym miesięczni-
ku ambitnych tematów.
Lekturę numeru proponujemy zacząć od artykułu Łukasza Mazura nt.
szybkiego i efektywnego tworzenia frontendów z użyciem frameworka
Twitter Bootstrap. Artykuł ten stanowi kontynuację artykułu z poprzed-
niego numeru Programisty. W tej części autor opisuje m.in. zmiany, któ-
re pojawiły się w wersji 3.0, oraz wybrane komponenty, jakie możemy
wykorzystać podczas tworzenia witryn.
Następnie zachęcamy do łatwego do „przełknięcia” artykułu z zakresu
tematyk miękkich. Michał Bartyzel i Mariusz Sieraczkiewicz opowiadają
krótko o najczęstszych błędach podczas budowania wiedzy w zespole
projektowym. Z kolei Sławomir Andrzejewski, codziennie pracujący nad
zapewnieniem niezawodności sieci komórkowych, omawia dobre prak-
tyki dotyczące przeprowadzania automatycznych testów akceptacyjnych.
Ponadto polecamy artykuły naszych dwóch nowych autorów: teksty Mi-
chała Charmasa będą traktować o zaawansowanych aspektach platfor-
my Android, natomiast Rafał Jamróz krok po kroku podpowie, jak radzić
sobie z utrzymaniem testów automatycznych.
Na koniec kilka słów o następnym numerze Programisty. Wielkimi kroka-
mi zbliża się rozszerzone wydanie grudniowe, a w nim znajdziecie szereg
ciekawych, mamy nadzieję, tematów, na czele z „Bliżej Silikonu #2 – O
analizie BIOS API, procesie ładowania jądra Windows, a także tworze-
niu boot loadera dla własnego systemu”. Będzie to druga (i nie ostatnia)
część cyklu autorstwa Gynvaela Coldwinda i Mateusza Jurczyka.
Powiększone wydanie to również debiuty nowych autorów – Bartek
Kuczyński zaproponuje temat „Vaadin 7 – naprawdę szybkie tworzenie
aplikacji web w Javie”, a wszystkich amatorów elektroniki na pewno zain-
teresuje artykuł Marka Klimowicza o robocie DIY reagującym na światło.
Wkrótce w newsletterach, na WWW i Facebooku będziemy ujawniać
więcej szczegółów na temat kolejnego wydania naszego magazynu.
Tymczasem życzymy przyjemnej i owocnej lektury
z poważaniem, Redakcja
Wydawca:
Anna Adamczyk
annaadamczyk@programistamag.pl
Redaktor naczelny:
Łukasz Łopuszański
lukaszlopuszanski@programistamag.pl
Korekta:
Tomasz Łopuszański
Kierownik produkcji:
Krzysztof Kopciowski
bok@keylight.com.pl
DTP:
Krzysztof Kopciowski
Dział reklamy:
reklama@programistamag.pl
tel. +48 663 220 102
tel. +48 604 312 716
Prenumerata:
prenumerata@programistamag.pl
Współpraca:
Michał Bartyzel
Mariusz Sieraczkiewicz
Artur Machura
Marek Sawerwain
Łukasz Mazur
Rafał Kułaga
Sławomir Sobótka
Michał Mac
Gynvael Coldwind
Bartosz Chrabski
Michał Leszczyński
Adres wydawcy:
Dereniowa 4/47
02-776 Warszawa
Druk:
ArtDruk – www.artdruk.com
ul. Napoleona 4
05-230 – Kobyłka
Nakład: 4500 egz.
* Redakcja zastrzega sobie prawo do skrótów
i opracowań tekstów oraz do zmiany planów
wydawniczych tj. zmiany w zapowiadanych tematach
artykułów i terminach publikacji, a także nakładzie
i objętości czasopisma.
O ile nie zaznaczono inaczej, wszelkie prawa do wszystkich materiałów zamieszczanych na łamach magazynu Programista są zastrzeżone.
Kopiowanie i rozpowszechnianie ich bez zezwolenia jest wzbronione. Naruszenie praw autorskich może skutkować odpowiedzialnością
prawną, określoną w szczególności w przepisach ustawy o prawie autorskim i prawach pokrewnych, ustawy o zwalczaniu nieuczciwej
konkurencji i przepisach kodeksu cywilnego oraz przepisach prawa prasowego.
Redakcja magazynu Programista nie ponosi odpowiedzialności za szkody bezpośrednie i pośrednie, jak również za inne straty i wydatki
poniesione w związku z wykorzystaniem informacji prezentowanych na łamach magazynu Programista. Wszelkie nazwy i znaki towarowe
lub firmowe występujące na łamach magazynu są zastrzeżone przez odpowiednie firmy.
Magazyn Programista wydawany
jest przez Dom Wydawniczy Anna
Adamczyk
SPIS TREŚCI
BIBLIOTEKI I NARZĘDZIA
Twitter Bootstrap – szybkie tworzenie witryn HTML. Co nowego w wersji 3.....
Łukasz Mazur
6
ASP.NET SignalR – czyli aplikacje czasu bardzo rzeczywistego...............................
Karol Rogowski
18
PROGRAMOWANIE APLIKACJI WEBOWYCH
Certyfikaty użytkownika SSL – jak to ugryźć?..............................................................
Michał Leszczyński
28
PROGRAMOWANIE GRAFIKI
Szybka grafika 2D: Shadery i tekstury...........................................................................
BartoszTaudul
32
PROGRAMOWANIE SYSTEMÓW OSADZONYCH
Arduino a sprawa wyświetlaczy.........................................................................................
Marek Sawerwain
42
TESTOWANIE I ZARZĄDZANIE JAKOŚCIĄ
Automatyczne testy akceptacyjne w procesie Continuous Delivery..........................
Sławomir Andrzejewski
52
LABORATORIUM BOTTEGA
Zaawansowane programowanie na platformie Android.
Część I: There is no app – kluczowe koncepty stojące za filozofią platformy Android...
Michał Charmas
56
Refaktoryzacja testów legacy w kierunku wykonywalnych specyfikacji.
Część I: Podstawowy refaktoring testów.........................................................................
Rafał Jamróz
60
PLANETA IT
Java nad Wisłą.....................................................................................................................
Łukasz Sobótka
68
KLUB LIDERA IT
Budowanie wiedzy w zespole. Główne błędy i strategie...............................................
Michał Bartyzel, Mariusz Sieraczkiewicz
70
KLUB DOBREJ KSIĄŻKI
Programowanie. Teoria i praktyka z wykorzystaniem C++......................................
Rafał Kocisz
72
Domain-Driven Design: Tackling Complexity in the Heart of Software................
Sławomir Sobótka
74
Zamów prenumeratę magazynu Programista bezpośrednio u nas przez formularz na stronie http://programistamag.pl/typy-prenumeraty/ lub zrealizuj ją na
podstawie faktury Pro-forma. W spawie faktur Pro-Forma prosimy kontktować się z nami przez e-mail redakcja@programistamag.pl.
Prenumerata realizowana jest też przez RUCH S.A: Zamówienia na prenumeratę w wersji papierowej i na e-wydania można składać bezpośrednio na stronie
www.prenumerata.ruch.com.pl Ewentualne pytania prosimy kierować na adres e-mail: prenumerata@ruch.com.pl lub kontaktując się z Telefonicznym Biurem
Obsługi Klienta pod numerem: 801 800 803 lub 22 717 59 59 – czynne w godzinach 7:00 – 18:00 (koszt połączenia wg taryfy operatora).
6 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
Łukasz Mazur
SŁOWEM WSTĘPU ...
Dzisiaj Internet jest bardzo ważnym medium, w którym można znaleźć
większość potrzebnych nam informacji. Podstawowym składnikiem Interne-
tu są strony i witryny www. Są one wizytówkami firm, blogów, poradników
czy różnych portali. Ważne jest, aby były one estetyczne i intuicyjne dla użyt-
kownika. Do ich budowy w większości używamy języka HTML w połączeniu z
arkuszem stylów CSS, które są interpretowane przez przeglądarkę i wyświe-
tlane na ekranie urządzenia (już nie tylko komputerów).
Responsywne strony
Obecnie wiele osób korzysta z urządzeń przenośnych takich jak: smartfony,
tablety czy ultrabooki, gdzie wielkość ekranu jest inna niż na komputerze typu
desktop (czy na laptopach). Aby strona wyświetlała się na tego typu urządzeniach
prawidłowo,możnaużyćdobudowywitrynyframeworkaTwitterBootstrap.Możli-
wośćtworzeniaresponsywnychstroninternetowychorazdodatkowewsparciedla
wielu gotowych rozwiązań czyni ten framework niezwykle przydatnym.
O Bootstrapie ...
Kilka słów przypomnienia o frameworku Twitter Bootstrap. Jest to narzędzie
mające ułatwić pracę developerom aplikacji webowych. Pozwala ono na łatwe i
szybkie tworzenie aplikacji w oparciu o standardy CSS i JavaScript. Powstał z po-
trzeby eliminacji problemów związanych z interfejsem graficznym tworzonych
aplikacji w firmie Twitter. Początkowo próbując rozwiązać te problemy, develo-
perzy korzystali z wielu wzajemnie niekompatybilnych bibliotek. Aby temu za-
pobiec, inżynierowie współpracujący z serwisemTwitter zdecydowali się opraco-
wać jeden, kompleksowy i w pełni spójny zestaw narzędzi developerskich.
W gruncie rzeczy Twitter Bootstrap to zestaw bibliotek CSS. Tym, co wy-
różnia go od podobnych rozwiązań, jest jego architektura. Framework oparty
został o elastyczny preprocesor LESS. Uzyskamy dzięki temu szereg przydat-
nych funkcji, m.in:
• możliwość zagnieżdżania deklaracji,
• operacje oraz funkcje koloru itp.
PonadtoTwitter Bootstrap jest bardzo łatwy do wdrożenia, a kompilacji LESS
można dokonać, używając np. JavaScript. Po kompilacji pakietów, Twitter Boot-
strap zawiera jedynie czysty CSS bez zbędnych dodatków, takich jak obrazy czy
kod JavaScript. Gwarantuje to szybkość działania oraz wysoki komfort użycia.
W poprzedniej części omówiono pobieranie, instalacje oraz uruchomie-
nie podstawowej strony wykonanej przy użyciu Twitter Bootstrap. W tej czę-
ści postaramy się przedstawić kilka wybranych komponentów (w tym opisać
bardziej szczegółowo tworzenie tabel oraz wykorzystanie karuzeli), które z
Twitter Bootstrap – szybkie tworzenie
witryn HTML. Co nowego w wersji 3
OmówieniewybranychelementówwTwitterBootstrap
W pierwszej części artykułu wyjaśniliśmy, jak zacząć przygodę z Twitter Bootstrap. Nato-
miast w tej części postaramy się przybliżyć ciekawsze jego elementy. Zaprezentowane
zostaną takie składniki jak wybrane komponenty, elementy JavaScript'u, w tym ich za-
stosowanie oraz finalnie responsive design. Dodatkowo opiszemy, co nowego pojawiło
się w wersji v3.0.0, czyli jakich zmian można się spodziewać w najnowszej odsłonie.
pewnością wzbogaca naszą witrynę, oraz dodatkowo zestawione będą waż-
niejsze zmiany, które wystąpiły w wersji v3.0.0.
TWITTER BOOTSTRAP V3.0.0 – ZMIANY
W drugą rocznicę releasu Twitter Bootstrap, dostarczono jego wersję
v3.0.0. Dla autorów zapewne to była szalona, długa i mozolna praca, ale final-
nie produkt jest już dostępny. Wszyscy, którzy wzięli udział w testowaniu wer-
sji RC (beta) oraz zgłaszali błędy czy także ulepszali kod, otrzymali od autorów
wielkie i szczere podziękowania. Bardzo ciężko było by opracować tego typu
narzędzie bez wsparcia społeczności.
Nowy Bootstrap
Niestety, już na samym początku potrzeba powiedzieć, żeTwitter Bootstrap
v3.0.0 może wprowadzić obecnych użytkowników w lekkie zakłopotanie, a
szczególnie za sprawą re-designu. Po gruntownym przeglądnięciu wprowa-
dzonych zmian można stwierdzić, że najświeższe wydanie może nie być naj-
lepsze dla wszystkich. Kiedy tylko przyjrzymy się dokumentacji, bez problemu
zauważymy, że wybrane aspekty kodu zostały sporo zmienione. W tym przy-
padku raczej nie jest to najlepszym rozwiązaniem (generalnie w softwarze wy-
chodzi to zazwyczaj na plus). Jednak teraz będziemy zmuszeni do pewnego ro-
dzaju przebudowy naszych aplikacji (czy też stron www) w próbie ewentualnej
migracji do nowej wersji. Główna, podstawowa struktura pozostała praktycznie
bez zmian. Jedynym wyjątkiem jest opcjonalna możliwość dodania responsyw-
nych elementów dla przeglądarki Internet Explorer 8 (Listing 1).
Listing1.SzablonpodstawowejstrukturystronyzwykorzystaniemBootstrap
Bootstrap 101 Template
Hello, world!
7/ www.programistamag.pl /
TWITTER BOOTSTRAP – SZYBKIE TWORZENIE WITRYN HTML
Została sporo zmieniona praca grid systemu, o czym później. Również do-
myślnie mamy włączony tryb responsive i nie ma już potrzeby, aby decydo-
wać, czy dołączyć bootstrap-responsive.less, oczywiście jest także możliwość
jego wyłączenia. Teraz można wybierać pomiędzy klasami, jak .col-sm dla
małych gridów czy .col-lg dla dużych. Oznacza to, że można dokładniej
precyzować, jak witryna będzie działać na smartfonach i tabletach, w przeci-
wieństwie do komputerów stacjonarnych.
Używając kodu:
div.sidebar {
make-column(3);
}
możemy utworzyć elementy zachowujące się jak kolumny, mimo że same
nie mają znaczników elementu.
Twitter Bootstrap nie wspiera już domyślnie starych przeglądarek. Jeżeli
jednak koniecznie chcemy włączyć możliwie najstarszy tryb zgodności dla IE,
powinniśmy w meta tagach witryny dodać następujący wpis:Nieco bliżej szczegółów
Nadal są wykorzystywane ikony ze zbioru Glyphicons, które zostały od-
świeżone i odrestaurowane. Można stwierdzić, że największym zmianom zo-
stał poddany grid system Bootstrapa. W dokumentacji widnieją nowe nazwy
klas CSS. Wprawiają one w lekkie zakłopotanie, jednak przy dłuższej pracy z
nimi nabierają dosyć logicznego sensu. Nie zmienia to jednak faktu, że tego
typu zmiany mogą wprowadzić niemało zamieszania i wymusić "przestawie-
nie się" na nowe nazewnictwo. Na szczęście wszelkie widoczne poprawki
typograficznych elementów nie zostały wprowadzone. Możemy cieszyć się
tekstem (przynajmniej w skompilowanej wersji) rodem z Twitter Bootstrap
2.3.2. Formularze i buttony należą do grupy elementów, które zyskały
nowy świeży wygląd, jednym się to spodoba, innym przeciwnie (flat design).
Najświeższe trendy wyolbrzymiają większość elementów, jednak ogromne
inputy tekstowe są mało poręczne. Drugą zmianą w designie jest usunięcie
wypukłości z kolorowych buttonów. O ile te z poprzedniej wersji były całkiem
ładne, to w tej chwili stały się trochę monotonne i jednokolorowe. JavaScrip-
t'owe dodatki pozostały w większości bez zmian. Oczywiście poprawiono ich
design, który jednym jak zwykle przypadnie do gustu, a innym już nie. Gene-
ralnie należy zwrócić również uwagę na dwojakie spojrzenie przez autorów
Twitter Bootstrap. Z jednej strony stawiają na minimalizm (płaskie buttony),
a z drugiej wciąż pozostawiono cienie wielu elementów – można postawić
tu małe pytanie: czy takie częściowo sprzeczne działania razem dobrze się
komponują?
Podsumowanie zmian
Dla tych, którzy nie mieli okazji śledzić bieżących zmian, oto krótkie zesta-
wienie tych ważniejszych, które wystąpiły w Bootstrap v3.0.0:
• Nowy design oraz opcjonalne motywy: w wersji v3.0.0 postawiono na pła-
ski flat design. Jak twierdzą autorzy, to nie jest tendencja – to wszystko po
to, aby ulepszyć możliwości dostosowywania. Uproszczona została estetyka
wyglądu, gdzie opcjonalny wybór tematu będzie z pewnością pomocny.
• Mobilne urządzenia na plan pierwszy (zawsze responsywne): prawie
wszystko zostało przeprojektowane i przebudowane, tak aby rozpocząć
od urządzeń przenośnych i skalować projekt w górę.
• Nowy Customizer: narzędzie zostało przeprojektowane, teraz elementy
są zgromadzone w przeglądarce zamiast w bazie Heroku. Posiada lepszą
obsługę zależności i dodatkowo ma wbudowaną obsługę błędów. Teraz
wygodniej możemy zapisać preferencje jako anonimowy gest dla łatwego
ponownego ich wykorzystania, udostępniania czy modyfikacji.
• Lepszy domyślny box model: wszystko w Bootstrap przyjmuje teraz
box-sizing: border-box, co dostarcza możliwości łatwiejszego dosto-
sowania rozmiaru i lepszej manipulacji w rozbudowanym grid systemie.
• Super-powered grid system: z czterema poziomami klas siatki, odpo-
wiednio dla: telefonów, tabletów, komputerów stacjonarnych i dużych
komputerów stacjonarnych.
• Przepisane wtyczki JavaScript: wszystkie zdarzenia obecnie znajdują się w
przestrzeni nazw, rzeczy no-conflict działają teraz o wiele lepiej i efektowniej.
• Ikony Glyphicons: przywrócono Glyphicons do głównego repozytorium.
W wersji 2.x występowały jako obrazki, teraz są one w formacie czcionki i
obejmują 40 nowych glifów.
• Zregenerowany pasek nawigacyjny: teraz jest on zawsze responsive i
został wyposażony w kilka przydatnych komponentów.
• Elementy modalne są bardziej elastyczne: przeprowadzono remont tej
części kodu, aby elementy były bardziej responsywne na urządzeniach
mobilnych. Teraz można przewijać obszar renderowania zamiast wcze-
śniej ustawionego sztywno max-height.
• Usunięto wybrane składniki: odrzucony został accordion (zastąpiono go
składanymi panelami), submenu oraz wpisywanie znaków z wyprzedzeniem.
• Bardziej spójne klasy: przyciski, tabele, formularze, alerty i inne zostały
zaktualizowane, po to aby uzyskać bardziej spójne klasy dla łatwiejszego
konfigurowania i rozszerzalności.
• Dodano nową dokumentację: nie tylko dla komponentów, ale dotyczą-
ce także wsparcia przez przeglądarki (w tym pułapek i różnych błędów),
najczęściej zadawane pytania FAQ odnośnie licencji, wsparcia dla kompo-
nentów third party oraz odnośnie dostępności.
• Odrzucony support dla Internet Explorer 7 i Firefox 3.6: dla Internet
Explorer 8 potrzeba dołączyć Respond.js dla wszystkich Media Queries w
celu pracy w pełnym zakresie.
Dla osób testujących prerelease i innych, które posiadają jeszcze wersję
RC, poniżej zestawiona została lista niektórych z bardziej znaczących zmian
wprowadzonych do RC:
• Zostały naprawione błędy zgłoszone w wersji RC,
• Odrestaurowano Glyphicons,
• Komponenty NavBars teraz wymagają .navbar-default dla wersji
standardowej,
• Panele teraz wymagają .panel-default dla standardowej (szarej),
• Alerty wymagają teraz klasę modyfikującą (np. .alert.alert-warning
– dla domyślnego wcześniej żółtego alertu),
• Wiele responsywnych narzędzi może być zastosowanych do tego samego
elementu,
• Przykłady są z powrotem w głównym repozytorium i zostały w pełni
zaktualizowane,
• Błędy kompilacji Customizera zostały naprawione,
• Dodano opcjonalne motywy,
• Jumbotrony są teraz wykonane w taki sposób, aby przedłużyć szerokość
obszaru wewnątrz kontenera. Odwracając to, spowodujemy, iż jumbotron
w kontenerze zostanie zaokrąglony i wcięty.
Rysunek 1. PrzykładJumbotronu
• Składniki NavBar zostały usprawnione z uwagi na obecność kontenerów
i innych elementów.
• Można zobaczyć kilka nowych modyfikacji w marginesach i wcięciach, ale
zmiana znaczników nie powinna być do tego wymagana.
8 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
WYBRANE KOMPONENTY
Kolejno zostanie zaprezentowanych kilka ważniejszych (ciekawszych)
komponentów, wchodzących w skład frameworka. W sekcji Bootstrapa (Com-
ponents) zgromadzono podstawowe style dla elementów interfejsu, takich
jak karty z treścią, panele nawigacyjne, paski postępu, przyciski, okienka
komunikatów (informacyjne, ostrzegawcze, błędów), nagłówki itp. Podczas
budowy naszej strony jest niezmiernie przydatnym, iż mamy tyle rzeczy do
wykorzystania niewielkim nakładem pracy – czy wręcz za darmo. Postaramy
się krótko zaprezentować kilka wybranych komponentów (ze względu na
dużą ich ilość nie sposób przedstawić wszystkich, więc w celu dokładnego
przejrzenia zachęcam do odwiedzenia strony Bootstrapa).
Komponenty zostały przedstawione na Rysunkach od 2 do 8. Kod użyty
do ich wyświetlenia zamieszczono na Listingach od 2 do 8.
Rysunek 2. Przykład dostępnych różnych typów alertów
Listing 2. Definiowanie alertów
...
...
...
...
Rysunek 3. Przykład dostępnych typów alertów z odnośnikami
Listing 3. Definiowanie alertów z odnośnikami
Rysunek 5. Przykładowy pasek nawigacji
Listing 5. Definiowanie paska nawigacjiGrupowanie przycisków
Przyciski nie muszą być pojedyncze, możemy tworzyć z nich grupy, grupy
grup, ustawiać je w pionie i zmieniać ich rozmiary. Grupę przycisków tworzymy
poprzez zamknięcie ich w div z klasą .btn-group. Bootstrap zadba, by pierwszy i
ostatni z nich miały zaokrąglone rogi, a środkowe były prostokątami (Rysunek 6).
Rysunek 6. Pojedyne przyciski i ich grupowanie w różnych konfiguracjach
Listing 6. Definiowanie grupy przycisków
...
...
...
...
Rysunek 7. Różne warianty przycisków typu dropdown
Listing 7. Definiowanie przycisków typu dropdown
TABELE
Przejdźmy teraz do opisu tabel. Jak wiemy, tabele bardzo często znajdują
swoje zastosowanie w wielu biznesowych rozwiązaniach. Twitter Bootstrap
posiada kilka klas, które umożliwiają ich dostosowywanie, a także zapewniają
estetyczny wygląd.
Podstawowa tabela
Tabele tworzymy poprzez HTMLowy znacznik
...
,
gdzie wystarczy dodać do niego klasę .table, by uzyskać w niej dopełnienie,
czy poziome linie oddzielające poszczególne wiersze (Listing 9).
Listing 9. Definiowanie prostej tabeli
#
Name
Surname
1
John
Doe
2
James
Smith
...
Dodatkowe klasy tabeli
Do klasy .table możemy dołączyć kilka opcjonalnych klas zmieniają-
cych sposób jej wyświetlania. Klasa .table-striped powoduje dodanie
ciemniejszego tła do co drugiego wiersza tabeli (Listing 10).
Listing 10. Ciemniejsze tło dla co drugiego wiersza w tabeli
...
Klasa .table-bordered automatycznie dodaje obramowanie do tabeli
(Listing 11).
Listing 11. Obramowanie tabeli
...
Klasa .table-hover powoduje podświetlenie wiersza, nad którym ak-
tualnie znajduje się kursor myszy (Listing 12).
Listing 12. Podświetlenie wiersza w tabeli
...
Klasa .table-condensed zmniejsza dopełnienie wewnątrz tabeli (Li-
sting 13).
10 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
Listing 13. Zmniejszenie dopełnienia wewnątrz tabeli
...
Dodatkowe klasy wierszy
Dzięki zastosowaniu klas .success, .error, .warning oraz .infomożli-
we jest nadawanie kolorów poszczególnym wierszom w tabeli (Listing 14).
Listing 14. Nadawanie kolorów poszczególnym wierszom w tabeli
#
Name
Surname
1
John
Doe
2
James
Smith
2
Paschal
Moris
...
Oczywiście możliwe jest stosowanie wielu klas dla tabeli, tak aby dostoso-
wać jej wygląd do naszych wymagań (Listing 15).
Listing 15. Wykorzystanie wielu klas w tabeli
#
Name
Surname
1
John
Doe
2
James
Smith
2
Paschal
Moris
...
Bardzo zachęcam do eksperymentowania, gdyż ten komponent posiada
szerokie możliwości i będzie bardzo przydatny, wzbogacając wszelkiego ro-
dzaju witryny wyświetlające wyniki analiz lub strony prezentujące grupowa-
ne dane w zwięzłej formie tabelarycznej.
KARUZELA
Karuzela służy do tworzenia galerii obrazów, które przewijamy za pomocą
elementów nawigacyjnych (strzałki) lub może odbywać się to automatycznie.
Zwykle wykorzystywana jest ona w głównej części strony, gdy chcemy po-
chwalić się swoim portfolio czy też przekazać ważne informacje o zawartości
naszego serwisu (np. kilku produktach). Należy pamiętać, iż rzadko użytkow-
nik będzie przewijał 50 czy więcej slajdów, więc lepiej zamieścić w niej rzeczy
najważniejsze z naszego punktu widzenia.
Rysunek 9. Komponent karuzela
Od strony programistycznej, gdy nie zamkniemy karuzeli w kontenerze,
będzie ona sięgała krawędzi okna przeglądarki, niezależnie od rozdzielczości.
Wspomniany kontener doda jej marginesy po bokach, a umieszczenie jej w
kolumnie pozwoli nam na ustalenie pożądanego rozmiaru. Występują dwa
rodzaje karuzeli: z opisem oraz bez opisu. Różnicą w kodzie jest dodanie tylko
jednego znacznika div (Listing 16).
Listing 16. Zamknięcie komponentu karuzeli w znaczniku div
...
gdzie id="carousel-example-generic" to dowolna nazwa kompo-
nentu, którą będziemy później wykorzystywać.
Odnośniki do slajdów
Kolejnym etapem w tworzeniu karuzeli są kropki (indykatory), które po-
zwalają przenieść się do konkretnego slajdu (Listing 17).
Listing 17. Dodanie nawigacji do karuzeliZapis data-target="#carousel-example-generic" musi prowadzić
do nazwy naszej karuzeli. A ilość wpisów w znaczniku
...
musi być
równa ilości slajdów. Klasa class="active" oznacza, który slajd ma być pierw-
szy. Oczywiście tak jak cały kod, są one wewnątrz pierwszego znacznika div.
Dołączenie slajdów
Nasze obrazki, które chcemy dodać, zamykamy również w znaczniku div
(Listing 18).
Listing 18. Obrazki zamknięte w znaczniku div
...
Dodatkowo wewnątrz znacznika każdy obrazek musi znajdować się w ko-
lejnym znaczniku div (Listing 19).
1and1.pl
NOWE DOMENY
NOWE MOŻLIWOŚCI
DOMENY | E-MAIL | STRONY WWW | HOSTING | SERWERY
Teraz w ofercie 1&1 mamy już ponad 700 nowych domen najwyższego
poziomu (nTLD). Stwórz chwytliwy adres, np. nowak.shop, serwis.auto
lub winiarnia.online i używaj go jako głównej lub dodatkowej domeny
dla Twojego serwisu. Będziesz jeszcze lepiej widoczny w Internecie!
W 1&1 zarejestrowaliśmy już około 20 milionów domen, co czyni nas
największym europejskim rejestratorem. Dzięki funkcji przekierowania,
z łatwością połączysz zarejestrowaną u nas domenę ze swoją stroną
internetową, nawet jeśli jest ona hostowana przez inną firmę.
Więcej informacji na 1and1.pl
TERAZ
REZERWUJ
ZA DARMO
I BEZ ZOBOWIĄZAŃ!*
*Wstępna rezerwacja nTLD jest bezpłatna i nie gwarantuje, że domena zostanie zarejestrowana. O przyznawaniu wstępnie zarezerwowanych nTLD decydują niezależne od 1&1 rejestry domen.
Więcej informacji na 1and1.pl oraz w regulaminach rejestrów domen.
12 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
Listing 19. Kolejny obrazek zamknięty w znaczniku div
Podołączeniuopisówdoslajdównaszkodbędziesięprezentowałnastępująco:
Listing 20. Dołączenie opisów do slajdów
Formularz i wyszukiwanie w menu
W pasku menu możemy także umieścić pole formularza lub wyszukiwa-
nia. Wystarczy w środku menu utworzyć formularz z klasą .navbar-form
lub .navbar-search i to wszystko. Przykład przedstawiono na Listingu 23.
Listing 23. Definiowanie pola formularza
Rozwijane menu
Możemy również stworzyć listę, która rozwija się po kliknięciu na nią mysz-
ką. Element menu, który ma być rozwijany, musi otrzymać klasę .dropdown,
a następnie musimy wstawić następujący kod przedstawiony na Listingu 24.
Listing 24. Definiowanie rozwijanego menu
...Element Name...
Dzięki temu otrzymamy rozwijany element, gdzie użyty kod odpowiada za ikonkę-strzałkę skierowaną w dół. Element listy
z klasą .divider wyświetla poziomą linię oddzielającą. Połączenie opisa-
nych elementów przedstawiono na Listingu 25.
13/ www.programistamag.pl /
TWITTER BOOTSTRAP – SZYBKIE TWORZENIE WITRYN HTML
Listing 25. Przykład rozwijanego menu
ELEMENTY JAVA SCRIPT'U
Dodatki JavaScript (JavaScript Plugins) są bardzo przydatne wszędzie tam,
gdzie zachodzi potrzeba umieszczenia interaktywnych elementów do witry-
ny takich jak: slidery, okienka akcji, tooltip'y, rozwijane menu itp. Właśnie ta-
kiego rodzaju elementy również zostały zaimplementowane w Bootstrap'ie,
po to, aby można łatwo z nich korzystać w projektach. Kolejno przedstawimy
tylko kilka wybranych komponentów (ponieważ wszystkich jest dosyć sporo),
aby pokazać, czego można się spodziewać (i próbować je wykorzystać) w tej
kategorii Bootstrapa podczas budowania witryny.
JavaScript alert
Przedstawiającelementyskładowe,wartonawstępiepowiedziećoalertach
posiadających możliwość oprogramowania zdarzeń dla funkcjonalności zamy-
kania. Wywołanie metody: $().alert() uzupełnia wszystkie klasy .alert o
funkcjonalność zamykania. Aby animować alert, podczas zamykania, upewnić
się potrzeba, iż klasy .fadeoraz .in są aktualnie dołączone do zastosowanego
znacznika. Wywołanie metody: $(".alert").alert('close') powoduje
jawne zamknięcie alertu. Klasa Bootstrap .alert udostępnia nam kilka zda-
rzeń dla połączania się z funkcjonalnością alertów, oto przykłady:
• close.bs.alert – zdarzenie jest wyzwalane natychmiast po tym, gdy
metoda bliskiej instancji jest wywołana.
• closed.bs.alert – zdarzenie jest wyzwalane po tym, gdy alert został
zamknięty.
Rysunek 10. Przykład alertu
Listing 26. Wywołanie alertu
$(".alert").alert()
Aby uzyskać automatycznie funkcjonalność zamykania naszego alertu,
wystarczy po prostu dodać data-dismiss="alert" do kodu wybranego przycisku.
Listing 27. Dodanie funkcji zamykania dla alertu×Modalne okna JavaScript
Okna modalne są przejrzyste, proste, ale i elastyczne, tzw dialogowe
prompty z minimalną (wymaganą) funkcjonalnością oraz posiadające inte-
ligentne wartości domyślne. Aby renderowanie modalnego okna z nagłów-
kiem mogło się odbyć, ciało oraz zestaw akcji powinien być umieszczony w
stopce strony. Chcąc uruchomić okna poprzez tzw. atrybuty danych (czyli
aktywacja okna bez użycia kodu JavaScript'u), potrzebujemy wykonać co
następuje. A mianowicie, ustawiamy data-toggle="modal" na elemencie
kontrolera (może nim być przykładowy przycisk), wraz z data-target="#-
foo" lub href="#foo", odnosząc się do określonego okna modalnego w
celu jego przełączenia.
Użycie wewnątrz znacznika:Z drugiej strony chcąc uruchomić okno, wykorzystując kod JavaScrip, wywoła-
nie takie (zakładając, iż id okna ma wartość myModal) prezentuje się następująco:
$('#myModal').modal(options).
Rysunek 11. Przykład wyświetlania modalnego okna
Listing 28. Deklaracja w kodzie modalnego okna
Modal title
One fine body…
JavaScript – popovery i tooltipy
Popover w Bootstrap jest tworzony przy użyciu niestandardowej wtyczki
jQuery. Może być używany do wyświetlania różnorakich informacji każdego
elementu. Poniżej można będzie zobaczyć, jak używać od początku popover
i tooltip, a także jak je dostosować za pomocą kilku dostępnych opcji.
14 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
Musimy dołączyć jQuery, Twitter Bootstrap CSS i dwa pliki JavaScript – je-
den dla komponentu tooltip Twitter Bootstrap i jeden dla popover Twitter
Bootstrap. Plik JavaScriptu popover jest dostępny w folderze JS z pakietu
Twitter Bootstrap jako bootstrap-popover.js oraz plik JavaScriptu dla tooltip
jest dostępny w folderze JS jako bootstrap-tooltip.js. JQuery jest dostępny pod
docs/assets/js jako jquery.js, lub może wskazywać na ten URL: http://code.jqu-
ery.com/jquery-1.10.2.min.js.
Popovery w grupach przycisków i grupach wejść wymagają specjalnych
ustawień. Podczas korzystania z popoverów na elementach .btn-group lub
.input-group, będziemy musieli określić opcję .container:'body', aby
uniknąć niepożądanych efektów ubocznych (takich jak szersze elementy lub
utrata zaokrąglonych rogów, gdy popover jest wyzwalany).
Dostępne są cztery opcje umiejscowienia: top, right, bottom i wyrów-
nanie do lewej left.
Ze względu na aspekty wydajności, API dla tooltip'ów i popover'ów są typu
option-in. Jeśli chcemy ich używać, potrzebujemy określić więc opcję selektora.
Poniżej zostaną wymienione poszczególne opcje uruchamiające komponent.
• $().popover(options).
• $('#element').popover('show') – pokazuje popover dla elementu.
• $('#element').popover('hide') – ukrywa popover dla elementu.
• $('#element').popover('toggle') – przełącza popover dla elementu.
• $('#element').popover('destroy') – usuwa popover dla elementu.
Rysunek 12. Przykład popoverów
Przykład:
$('#myPopover').on('hidden.bs.popover', function () {
// do something
})
Rysunek 13. Przykład tooltipów
Podobnie jak popovery – tooltipy w grupach przycisków i grupach wejść
wymagają specjalnych ustawień. Podczas korzystania z tooltipów na ele-
mentach .btn-group lub .input-group będziemy musieli określić opcje
.container:'body'', aby uniknąć niepożądanych efektów ubocznych (ta-
kich jak szersze elementy lub utrata zaokrąglonych rogów, gdy tooltip jest
wyzwalany). Opcje dla poszczególnych tooltipów można alternatywnie okre-
ślić z wykorzystaniem atrybutów danych, jak pokazano poniżej:
Użycie wewnątrz znacznika:Hover over mePoszczególne opcje uruchamiające komponent:
• $().tooltip(options).
• $('#element').tooltip('show') – pokazuje tooltip dla elementu.
• $('#element').tooltip('hide') – ukrywa tooltip dla elementu.
• $('#element').tooltip('toggle') – przełącza tooltip dla elementu.
• $('#element').tooltip('destroy') – usuwa tooltip dla elementu.
Przykład:
$('#myTooltip').on('hidden.bs.tooltip', function () {
// do something
})
RESPONSIVE WEB DESIGN
Responsive Web Design jest funkcjonalnością zapewniającą użytkow-
nikowi uzyskanie najlepszych odczuć (user experience) podczas przeglą-
dania stron internetowych na różnych urządzeniach (posiadających różne
rozmiary).
Na przykład, w przypadku przeglądania strony internetowej na monito-
rze komputera, a następnie wyświetlania jej na smartfonie (gdzie rozmiar jest
mniejszy niż rozmiar monitora komputera), nie powinna występować większa
różnica podczas pracy z UI. Inaczej mówiąc, powinniśmy mieć złudzenie, iż
jesteśmy w tym samym serwisie (miejscu). Chcąc uzyskać tego typu wrażenia,
potrzeba na takiej stronie uaktywnić elementy odpowiedzialne za mecha-
nizm responsive design.
Aby testować zachowanie strony, można zmieniać rozmiar przeglądarki
za pomocą zmiany rozmiaru okien. Pomocnym będzie wtedy rozszerzenie
Window Resizer dla przeglądarek Chrome czy Firefox.
Jak działa responsive design? Do pracy z responsive design potrzeba
stworzyć CSS, który zawiera style odpowiednie dla różnych urządzeń o róż-
nych zakresach rozmiarów. Gdy strona ma się załadować na konkretnym
urządzeniu, za pomocą różnych technik front-endu jak kwerendy mediów
(Media Queries – które pozwalają dostosować styl do dokumentu oparty na
środowisku, w którym dokument ten jest renderowany), wielkość obszaru
wyświetlania musi zostać wykryta, po czym specyficzny styl dla urządzenia
jest ładowany.
Przejdźmy teraz nieco w głąb Responsive Design CSS początkowo opie-
rając się na przykładzie wcześniejszej wersji Bootstrapa v2.3.2. Weźmy pod
uwagę integrację 'bootstrap-responsive.css' z naszą stroną i postarajmy się zro-
zumieć, w jaki sposób działanie tego mechanizmu zostało osiągnięte.
Na wstępie musimy pamiętać, iż potrzeba dodać następujący wiersz we-
wnątrz sekcji head naszej strony internetowej:Meta tag viewport jest powszechnie używany, jako że zastępuje on do-
myślny i pomaga załadować styl związany z konkretnym obszarem wyświe-
tlania. Właściwość width ustawia szerokość ekranu. Może ona zawierać war-
tości numeryczne jak 320, oznaczając 320 pikseli, lub może posiadać wartość
'device-width', która informuje przeglądarkę, aby skorzystać z natywnej
rozdzielczości (lub szerokości – dla uproszczenia) urządzenia. Właściwość
initial-scale jest początkową skalą obszaru wyświetlania jako mnożnik.
Tak więc, gdy jest ustawiona na 1.0, to oznacza wtedy natywną szerokość dla
danego urządzenia. Oczywiście, po tym należy dodać responsive CSS z Boot-
strap, jak pokazano na poniższym kodzie:Teraz, gdy spojrzymy na plik responsive CSS, możemy zauważyć, że po
deklaracji pewnych ogólnych składników (linie ~10 do 22) istnieją wyspecy-
fikowane różne sekcje zaczynające się od znacznika '@media'. Mamy tam
zdefiniowane style dla różnych wielkości urządzeń:
MISSION CODE
ACHIEVE NEW LEVEL
JOIN THE CREW
16 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
• Pierwsza z tych sekcji rozpoczyna się od znacznika '@media (max-
width: 480px)', który określa style dla urządzeń, gdzie maksymalna
szerokość jest równa 480 pikseli.
• Druga sekcja rozpoczyna się od znacznika '@media (max-width:
767px)', który określa style dla urządzeń, gdzie maksymalna szerokość
jest równa 767 pikseli.
• Trzecia sekcja rozpoczyna się od znaczników '@media (min-width:
768px) oraz (max-width: 979px)', zapis ten określa style dla urzą-
dzeń, których minimalna szerokość wynosi 768 pikseli, a maksymalna
szerokość to 979 pikseli.
• Następna sekcja jest określona dla urządzeń z maksymalną szeroko-
ścią 979 pikseli, więc zaczyna się od znacznika '@media (max-width:
979px)'.
• Ostatnie dwie sekcje zaczynają się od znaczników '@media (min-
width: 980px)' oraz '@media (min-width: 1200px)', więc są prze-
znaczone dla urządzeń o minimalnej szerokości 980 pikseli i 1200 pikseli.
Funkcją, jaką spełnia ten arkusz, jest więc przechowywanie stylów według
minimalnej i maksymalnej szerokości urządzeń korzystających z właściwości
'min-width' oraz 'max-width'. Aby układ responsive mógł być osiągnię-
ty, Twitter Bootstrap wykonuje kolejno trzy rzeczy:
1. Modyfikuje szerokości kolumny w siatce.
2. Ilekroć jest wymagane, używa stosu elementów zamiast elementu
pływającego,
Element główny (html) tworzy korzeń kontekstu układania. Inne kontek-
sty układania są generowane przez umieszczanie kolejnych elementów (w
tym elementów pozycjonowanych relatywnie) o wyliczonej wartości 'z-in-
dex' innej niż 'auto'.
3. Aby renderować prawidłowo nagłówki i tekst, zmienia ich rozmiary w ra-
zie potrzeby.
NARZĘDZIARESPONSYWNEWWERSJI3.0.0
W dzisiejszych czasach coraz więcej osób przegląda strony www za pomocą
różnych urządzeń mobilnych. Praktycznie każdy nowoczesny telefon czy tablet
umożliwia w jakimś stopniu korzystanie z Internetu. Jako projektanci musimy
zadbać o to, aby zapewnić takim osobom jak najłatwiejszy dostęp do treści i
funkcjonalności witryny. Prawidłowe dostosowanie strony do urządzeń mo-
bilnych sprawi, że szerokie grono osób będzie mogło ją wygodnie przeglądać.
Projektowanie stron na przeglądarki mobilne nie jest łatwym zadaniem.To zło-
żony temat, który obejmuje zarówno aspekty wizualne, jak i funkcjonalne.
W celu szybszego rozwoju interfejsów wspierających zastosowania mo-
bilne (mobile-friendly), potrzeba korzystać z klas użytkowych służących do
pokazywania/ukrywania zawartości poprzez urządzenia, wykorzystując Me-
dia Queries. Szybsze rozwijanie takich interfejsów jest możliwe dzięki Twitter
Bootstrap, który teraz również posiada zestaw klas użytkowych dla przyśpie-
szenia tego procesu. Klasy te są dostępne w module 'responsive-utilities.less'.
Należy używać ich w ograniczonym zakresie, unikając tworzenia różnych
wersji tej samej witryny (w celu uzupełnienia prezentacji dla każdego urzą-
dzenia). Narzędzia responsywne są obecnie dostępne tylko w blokach i w
przełączeniu tabeli (block and table toggling). Korzystanie z nich inline oraz
jako elementów tabeli nie jest aktualnie obsługiwane. Można wykorzystać
jedną klasę lub kombinacji dostępnych klas w celu przełączania zawartości w
bieżących wartościach granicznych obszaru wyświetlania.
Warto opanować najważniejsze techniki responsywne, czyli takie, które po-
zwolą nam dostosować witrynę do różnych urządzeń. Poznać podstawowe zasa-
dy tworzenia witryn responsywnych, dowiedzieć się, jak wykorzystać możliwości
Media Queries oraz jak stworzyć płynny układ kolumn. Poznać przydatne rozwią-
zania, umożliwiające dostosowanie typowych elementów strony, jak: obrazki,
tabele oraz menu do mobilnych przeglądarek. Framework Bootstrap oferuje sze-
roki zestaw klas i skryptów, które pozwolą łatwo i szybko stworzyć responsywną
strukturę witryny, dodać style oraz różne przydatne funkcjonalności.
Rysunek 14. Ilustracja obrazująca filozofię Responsive Design
17/ www.programistamag.pl /
TWITTER BOOTSTRAP – SZYBKIE TWORZENIE WITRYN HTML
Rysunek 15. Zestawienie klas dla przełączania zawartości bieżącego obszaru
wyświetlania w wersji 3.0.0
PODSUMOWANIE
W drugiej części artykułu omówiono wybrane ważniejsze (z punktu wi-
dzenia developera) komponenty będące składnikami frameworka. Opisano
również ważniejsze zmiany występujące w wersji v3.0.0, która jest oficjalną
wersją produkcyjną. Twitter Bootstrap obecnie implementuje flat design, co
w przypadku stron internetowych nie zawsze jest pożądane. Wystąpiły pew-
ne zmiany w nazewnictwie oraz strukturze i teraz nie wszystko, co było do-
stępne w v 2.3, jest dostępne także w v3.0.0. Zmiana niektórych nazw klas być
może ma sens, ale utrudnia aktualizację do najnowszej wersji. Można pokusić
się o ponowną kompilację plików LESS, przywracając poprzednie nazewnic-
two, ale będzie to pracochłonne.
Podsumowując – dzięki wykorzystaniu bibliotek Bootstrap'a rozwijane
aplikacje internetowe tworzone są szybciej, będą się cechowały skalowalno-
ścią oraz przyjaznym interfejsem użytkownika. Bezbłędne działanie pakietu
jest zagwarantowane przez twórców w przeglądarkach Chrome, Safari oraz
Firefox. Można zaznaczyć, że wciąż trwają także prace nad polepszeniem wy-
dajności obsługi dla przeglądarki Internet Explorer.
Zdobytą wiedzę możemy bez przeszkód zastosować do utworzenia wła-
snej witryny oraz poszerzyć swoje umiejętności w zakresie tworzenia este-
tycznie wyglądających, responsywnych stron. Dzięki Bootstrapowi proces
ten będzie łatwy i przyjemny. Koniec z wyliczaniem marginesów, tworzeniem
form czy ramek od podstaw – Twitter Bootstrap zrobi to za nas. Korzystając
ze skalowalności, nasza strona będzie dobrze wyglądała na komputerze, ta-
blecie czy smartfonie. Wykorzystanie frameworka przy projektowaniu strony
przyspieszy nam pracę oraz zwiększy zadowolenie z efektu końcowego.
W sieci
PP http://twitter.github.com/bootstrap/–zasobyTwitterBootstrapv2.3.2.
PP http://themecrunch.com/2013/04/twitter-bootstrap-tutorials-tools-
and-resources/ – zasoby oraz tutoriale dlaTwitter Bootstrap.
PP http://getbootstrap.com/components/ – dokumentacja dla
komponentówTwitter Bootstrap v3.0.0.
PP http://getbootstrap.com/css/ – dokumentacja modułu CSS dla
Twitter Bootstrap v3.0.0.
PP http://getbootstrap.com/javascript/ – dokumentacja JavaScript dla
Twitter Bootstrap v3.0.0.
PP http://www.bootstraptor.com/bootstrap3 – zestawy szablonów i
motywy zbudowane przy wykorzystaniuTwitter Bootstrap v3.0.0.
PP http://www.w3resource.com/twitter-bootstrap/responsive-design.php–
ResponsiveWebDesignprzywykorzystaniuTwitterBootstrap–artykuł.
PP http://getbootstrap.com/customize/ – moduł pobierania frameworka
wraz z panelem personalizowania.
PP http://getbootstrap.com/getting-started/#migration – ważniejsze
zmiany pomiędzy wersjami 2.x a 3.0.0.
PP http://bradfrostweb.com/blog/web/mobile-first-responsive-web-
design/ – blog traktujący o tematyce Responsive Design
Łukasz Mazur lukash.mazur@gmail.com
Autor obecnie jest programistą/architektem aplikacji biznesowych dedykowanych na
platformy mobilne. Pracuje dla irlandzkiej firmy Mobile Travel Technologies Ltd. Dodatkowo
poszerza swoja wiedzę dotyczącą zagadnień analityki biznesowej w Institute of Technology
Blanchardstown – Dublin na wydziale Computing Business Intelligence & Data Mining.
18 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
Karol Rogowski
S
koro już wiemy, czym są aplikacje czasu rzeczywistego, a jeszcze nie
zdążyliśmy przejść do żadnej konkretnej rozmowy technicznej, to zasta-
nówmy się, czy faktycznie jest tego aż tak wiele, żeby było warto zaprzą-
tać sobie tym głowę. Zacznijmy może od portali społecznościowych, które to
ostatnio na całym świecie zdobywają coraz większą popularność. Nie mówię
już nawet o kwestiach rozmów, ponieważ konieczność dostawania tam danych
na żywo jest kwestią bezdyskusyjną. Zauważmy też, że każda niemalże akcja
innych użytkowników mająca z nami jakiś związek skutkuje natychmiastowym
poinformowaniem nas o tym. Portale społecznościowe nie są oczywiście jedy-
ne, jeżeli chodzi o konieczność posiadania świeżych danych. Spójrzmy na przy-
kład na wszelkiego typu notowania. Czy to giełdowe czy też związane z wy-
nikami sportowymi. Dodatkowo są też najróżniejsze aplikacje pozwalające na
jednoczesną interakcję ze sobą kilku użytkowników.Tak, wiem, że pierwszą na-
chodzącą myślą są gry interaktywne, ale to nie jest jedyny przykład. Są przecież
też sytuacje, gdy jednocześnie musimy pracować nad jakimś dokumentem.
Przykłady tego typu można by mnożyć jeszcze długo. Ale mam nadzieję,
że udało mi się już zobrazować skalę problemu posiadania realnych danych
oraz to, że naprawdę istnieje szeroki rynek na tego typu rozwiązania.
PUSH SERVICE
Zanim zaczniemy omawiać konkretne rozwiązanie technologiczne, po-
wiedzmy sobie, w jaki sposób odbywa się komunikacja w omawianych apli-
kacjach. Bazuje ona na wzorcu zwanym Push Service. I chociaż bardzo się
starałem, to nie udało mi się wymyśleć tłumaczenia na polski, które nie wy-
paczałoby treści zawartej w oryginalnej nazwie. Dlatego właśnie zostaniemy
przy nazwie anglojęzycznej. Push Service, najogólniej mówiąc, ma za zadanie
dostarczanie i rozdzielanie komunikatów. Przyjrzyjmy się rysunkowi poniżej,
a następnie omówimy dokładniejszą budowę tego wzorca.
Rysunek 1. Budowa wzorca Push Service
Jak widzimy powyżej Push Service opiera się na synchronizacji współ-
pracy podpiętych do niego klientów oraz zdarzeń. Klienci w tym przypadku
powinni być rozumiani jako wszelkiego rodzaju aplikacje chcące korzystać z
powiadomień dostarczanych przez serwis. Z drugiej strony mamy natomiast
zdarzenia, których wystąpienie powoduje wysłanie powiadomień do odpo-
wiednich klientów. Natomiast klienci po otrzymaniu powiadomienia już po
swojej stronie odpowiednio na nie reagują. Wiem, że na pewno taki schemat
nie zobrazuje od razu wszystkiego, ale na pewno da jakiś pogląd na to, co
chcemy osiągnąć.
SIGNALR
Na początku powiedzmy sobie, czym w ogóle jest SignalR. Jest to Frame-
work pozwalający nam na tworzenie Push Service-ów. Składa on się z dwóch
części. Pierwszą z nich jest zestaw rozwiązań serwerowych, które służą nam
do faktycznego budowania tego, w jaki sposób ma wyglądać nasz serwis,
oraz z części klienckiej. Odpowiedzialna jest ona za możliwość komunikacji z
serwisem. Dzięki odpowiednim bibliotekom pozwala ona na komunikację z
praktycznie każdą platformą. Jest to bardzo ważne, ponieważ ciężko jest wy-
magać, aby wszystko pracowało na .NET-cie.
Ogólna idea działania tej technologii jest poniekąd schowana w jej na-
zwie. Chodzi mianowicie o to, że powinniśmy operować na sygnałach. Po-
przez sygnał rozumiemy wysłanie małej porcji danych, która zostaje już po
stronie odczytującej ją aplikacji odpowiednio zinterpretowana. Powinniśmy
się wystrzegać przesyłania przy użyciu SignalR całych dużych kawałków da-
nych. Jeżeli chcemy napisać sygnał, który będzie informował o zmianach w
którymś z elementów wyświetlanych na naszej stronie, powinno to się odbyć
następująco: Sygnał informuje nas o tym, że dany element się zmienił. Może
to zrobić na przykład poprzez wysłanie jego identyfikatora. Dopiero nasza
aplikacja po odpowiedniej interpretacji sygnału pobiera oddzielnym zapyta-
niem nowe dane i obsługuje je na właściwy sposób.
NAPISZMY COŚ
Jak już pewnie zdążyliście zauważyć, w swoich artykułach staram się kłaść
możliwie jak największy nacisk na praktyczne wykorzystanie technologii
i w ten sposób zapoznawać Was z jej działaniem. Nie inaczej będzie w tym
przypadku. Napiszemy Push Service, który to będzie obsługiwał scenariusz
prostego chatu. Nie jest to może jakiś bardzo skomplikowany i wyrafinowa-
ny przykład, ale pozwoli zaznajomić się ze sposobem działania omawianej
technologii. A jeżeli ktoś będzie chciał dalej się tego uczyć, to będzie miał już
gotowe podwaliny.
Pierwszym krokiem, jaki należy wykonać, jest utworzenie pustej aplika-
cji ASP.NET MVC4, na której będziemy pracować. Kolejną czynnością będzie
dodanie do naszego projektu Hub-a. Hub jest to klasa, w której będziemy
ASP.NET SignalR – czyli aplikacje
czasu bardzo rzeczywistego
Aplikacje czasu rzeczywistego to rozwiązania, które dostarczają dane na bieżąco.
Powiedzmy na przykład, że chcemy przeczytać sobie poranne wiadomości na którymś
z licznych istniejących w sieci portali. Dane powinny tam być możliwie świeże, z tym że
nie są one raczej dostarczane na żywo, a po prostu pobierają się podczas naszego wej-
ścia na stronę. Wszystko w tej sytuacji jest ok, ponieważ nie oczekujemy chyba odświe-
żania ich co chwilę. Inaczej sytuacja wygląda, jeżeli chodzi np. o chat na jakimś portalu
społecznościowym. Tutaj otrzymywanie danych na żywo jest kwestią krytyczną.
19/ www.programistamag.pl /
ASP.NET SIGNALR – CZYLI APLIKACJE CZASU BARDZO RZECZYWISTEGO
definiować zachowania naszego serwisu. Będą się tam znajdować zarówno
wymagane zdarzenie, jak i te metody, które są charakterystyczne tylko dla
naszego rozwiązania. Klasę taką możemy dodać, jako jeden z już przygoto-
wanych elementów.
Rysunek 2. Dodawanie nowego Hub-a
Po kliknięciu przycisku Add do naszego projektu zostanie dodany nowy
element. Oprócz tego, że widzimy teraz nowy plik, to warto zwrócić uwagę na
trzy nowe referencje, które pojawiły się w naszym rozwiązaniu. Są to bibliote-
ki Microsoft.AspNet.SignalR.Core, Microsoft.AspNet.SignalR.Owin oraz Micro-
soft.AspNet.SignalR.SystemWeb. Jak łatwo można zgadnąć, są to elementy
odpowiedzialne za działanie technologii SignalR w naszej aplikacji.
Zajrzyjmy teraz do naszego nowego pliku.
Listing 1. Zawartość pliku ChatHub.cs
namespace ExampleChat
{
using Microsoft.AspNet.SignalR;
/// /// Klasa huba naszego projektu
/// public class ChatHub : Hub
{
public void Hello()
{
Clients.All.hello();
}
}
}
Widzimy, że nowoutworzona klasa ma tak naprawdę bardzo prostą budo-
wę. Jedynym elementem, na jaki należy w tym momencie zwrócić uwagę, jest
jej dziedziczenie po klasie Hub. Co z tego dziedziczenia wynika, zobaczymy
już za chwilę.
Zanim jednak przejdziemy do implementacji funkcjonalności, musimy
poinformować aplikację, że będzie ona korzystała z hub-ów. Robimy to pod-
czas zdarzenia startu aplikacji. Możemy oczywiście znaleźć je w pliku Global.
asax. Zarejestrowanie hub-ów musi odbyć się od razu po wywołaniu akcji
RegisterAllAreas(). Jest to bardzo ważne, ponieważ w przeciwnym wy-
padku nasze rozwiązanie w ogóle nie zadziała.
Listing 2. Prawidłowa rejestracja Hub-ów w pliku Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteTable.Routes.MapHubs();
WebApiConfig.Register(GlobalConfiguration.
Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.
Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
Skoro nasza aplikacja już wie, że ma korzystać z hub-ów, zastanów się te-
raz, jakie w ogóle funkcjonalności chcemy zaimplementować. Po pierwsze,
musi być możliwość wysyłania wiadomości. Fajnie też by było móc nadać
sobie jakieś imię. Funckjonalnością jakby oczywistą jest możliwość otrzymy-
wania informacji. Jako bonus dajmy naszemu rozwiązaniu odrobinę prywat-
ności. Powiedzmy, że damy użytkownikom możliwość spotykaniu się w poko-
jach i rozmawiania tylko wewnątrz nich. To byłoby chyba na tyle, jeżeli chodzi
o opcje. Jeśli jeszcze jakaś nasunie się w trakcie, to będziemy uzupełniać tę
listę na bieżąco.
Wszystkie te zdarzenia należy zakodować oczywiście w naszym Hub-ie.
Może zróbmy to w ten sposób, że zaprezentuję od razu gotowy i, wydaje mi
się, dość czytelnie okomentowany kod, a następnie będę omawiał kolejne
elementy i w ten sposób tłumaczył, co tam się dzieje.
Listing 3. Zaprogramowana klasa Hub-a
/// /// Klasa Hub-a naszego chat-u
/// [HubName("ExampleChat")]
public class ChatHub : Hub
{
/// /// Metoda pozwalająca na wysłanie wiadoności do
wszystkich użytkowników
/// /// Nazwa użytkownika/// Treść wiadomościpublic void SendMessage(string name, string message)
{
var msg = string.Format("{0}: {1}", name, message);
Clients.All.newMessage(msg);
}
/// /// Metoda pozwalająca na połączenie to jakiegoś pokoju
/// /// Nazwa użytkownika/// Nazwa pojoku to którego chcemy
podączyćpublic void JoinRoom(string name, string room)
{
Groups.Add(Context.ConnectionId, room);
var msg = string.Format("{0} joined room: {1}", name,
room);
Clients.Group(room).newMessage(msg);
}
/// /// Metoda pozwalająca na wysłanie wiadoności do
użytkowników w danym pokoju
/// /// Nazwa użytkownika/// Nazwa pokoju/// Treść wiadomościpublic void SendMessageToRoom(string name, string room,
string message)
{
var msg = string.Format("{0}: {1}", name, message);
Clients.Group(room).newMessage(msg);
}
/// /// Nadpisane zdarzenie na łączenie się z Hub-em
/// /// Obiekt odpowiedni dla metody którą
nadpisujepublic override Task OnConnected()
{
this.SendMonitoringData("Połączono", Context.
ConnectionId);
20 / 10 . 2013 . (17) /
BIBLIOTEKI I NARZĘDZIA
return base.OnConnected();
}
/// /// Nadpisane zdarzenie na rozłączenie się z Hub-em
/// /// Obiekt odpowiedni dla metody którą
nadpisujepublic override Task OnDisconnected()
{
this.SendMonitoringData("Rozłączono", Context.
ConnectionId);
return base.OnDisconnected();
}
/// /// Nadpisane zdarzenie na ponowne połączenie się z
Hub-em
/// /// Obiekt odpowiedni dla metody którą
nadpisujepublic override Task OnReconnected()
{
this.SendMonitoringData("Połączono ponownie",
Context.ConnectionId);
return base.OnReconnected();
}
/// /// Metoda pozwalająca na informaowanie użytkowników o
zdarzeniach występujących na Hub-ie
/// /// Rodzaj zdarzenia/// Identyfikator połączenie
które wywołało to zdarzenieprivate void SendMonitoringData(string eventType, string
connection)
{
Clients.All.newEvent(eventType, connection);
}
}
Tak jak obiecałem, tak też teraz zrobię. Skoro każdy już przeczytał zapre-
zentowany kod, możemy przejść do szczegółowego omawiania go. Pierw-
szym elementem, jaki rzuca nam się w oczy, jest atrybut HubName; pozwala
on na ustawienie nazwy naszego Hub-a. Do czego konkretnie może się to
przydać, zobaczymy w kolejnym listingu. W pełni natomiast zrozumiemy to
podczas kolejnego artykułu, gdy będziemy pisać klientów rozmawiających
na czacie.
Pierwszą publiczną metodą jest SendMessage. Pozwala ona na wysłanie
wiadomości do wszystkich podłączonych klientów. Właśnie w tym momen-
cie chciałbym, abyśmy zobaczyli, jak wygląda komunikacja z klientami. Po
pierwsze, omawiana właśnie metoda musi być wywołana przez klienta. Jak
on to robi, będzie wyjaśnione w kolejnej części artykułu. W tym momencie in-
teresuje nas kontakt od serwera do klienta. W tym przypadku chcemy wysłać
sygnał do wszystkich klientów. Dlatego właśnie z obiektu Clients skorzystali-
śmy z właściwości All, która to oczywiście zwraca nam wszystkich klientów.
Następnie już sami, bez żadnych podpowiedzi, definiujemy metodę oraz pa-
rametry, które zostaną wysłane do klientów ze zbioru All. Kolejną metodą jest
JoinRoom.Tak jak już mówliśmy, każdy potrzebuje czasami odrobiny prywat-
ności. Dlatego właśnie SignalR oferuje nam możliwość wysyłania sygnałów
tylko do klientów będących w pewnej grupie. Właśnie za to odpowiada nasza
metoda. Na początku widzimy kod, który dodaje identyfikator połączenia, z
którego została wywołana ta metoda do pokoju o nazwie przekazanej para-
metrem. Na końcu, tak jak poprzednio, wysyłamy wiadomość do odpowied-
nich klientów. Z tym, że tym razem nie są to już wszyscy klienci, a jedynie
ci należący do tego pokoju (do tej grupy). Zrobiliśmy to poprzez wywołanie
na obiekcie Clients metody Group, zamiast właściwości All. Kolejna przedsta-
wiona metoda daje nam możliwość wysłania wiadomości tylko do klientów z
danej grupy. Nie ma tu żadnych nowych konstrukcji, jeżeli chodzi o kod, nie
będziemy więc się na niej zatrzymywać.
Kolejne trzy kroki będzie stanowić nadpisanie zdarzeń z klasy bazowej.
Jest to bardzo charakterystyczne zachowanie, jeżeli chodzi o programowanie
obiektowe, dlatego też, jeżeli ktoś ma problem ze zrozumieniem tej części
kodu, to zachęcam do douczenia się. Wiedza ta na pewno się przyda. Co do
zawartości tych metod, to każda z nich zawiera odwołanie do metody, która
to ma monitorować aktywności na naszym Hub-ie. Następnie oczywiście wy-
wołujemy nadpisane zdarzenie z klasy bazowej, dzięki czemu działanie naszej
aplikacji nie zostanie zachwiane.
Ostatnim elementem stworzonym w klasie jest metoda pozwalająca na
obronienie monitorowanych akcji. W przypadku realnej aplikacji w tym miej-
scu znajdowałby się prawdopodobnie kod w jakiś sposób monitorujący za-
chodzące zdarzenie. Jako że jest to aplikacja demonstracyjna, to będziemy
po prostu wysyłać informacje o zdarzeniach do wszystkich podłączonych
klientów.
Skoro mamy już wszystko przygotowane, to uruchommy naszą aplikację i
zobaczmy, co się stanie. Chwila napięcia….
No i nie stało się nic, a na pewno nic pozytywnego. Otrzymaliśmy ekran
błędu mówiący, że poszukiwane zasoby nie zostały odnalezione. Nie ma czym
się martwić, bo ten ekran jest dokładnie tym, co powinniśmy w tym momen-
cie widzieć. Zastanówmy się, co tak naprawdę oczekiwaliśmy, że zobaczymy.
Jakiś napis typu:„Nie masz żadnych kontrolerów ani widoków, ale nie martw
się, wszystko na pewno działa”? Niestety nie jest tak pięknie.
Rysunek 3.Widok aplikacji po uruchomieniu
Skoro teraz widzimy błąd, to pozostaje pytanie, jak sprawdzić, czy apli-
kacja faktycznie działa. Dla nas działanie aplikacji oznacza ni mniej ni więcej
niż to, że działa nasz Hub-a. Możemy to sprawdzić pod poniższym adresem:
http://localhost:58033/signalr/hubs. Jeżeli wszystko zaprogramowaliśmy po-
prawnie, to powinniśmy zobaczyć w ekranie przeglądarki kod Hub-a, którego
w trakcie artykułu stworzyliśmy.
Listing 4. Kod działającego Hub-a
/*!
* ASP.NET SignalR JavaScript Library v1.0.0
* http://signalr.net/
*
* Copyright Microsoft Open Technologies, Inc. All rights
reserved.
* Licensed under the Apache 2.0
* https://github.com/SignalR/SignalR/blob/master/LICENSE.md
*
*/
/// /// (function ($, window) {
if (typeof ($.signalR) !== "function") {
throw new Error("SignalR: SignalR is not loaded. Please
ensure jquery.signalR-x.js is referenced before ~/
signalr/hubs.");
}
var signalR = $.signalR;
function makeProxyCallback(hub, callback) {
return function () {
// Call the client hub method
callback.apply(hub, $.makeArray(arguments));
};
}
$.hubConnection.prototype.createHubProxies = function () {
21/ www.programistamag.pl /
ASP.NET SIGNALR – CZYLI APLIKACJE CZASU BARDZO RZECZYWISTEGO
reklama
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this._registerSubscribedHubs();
}).disconnected(function () {
// Unsubscribe all hub proxies when we "disconnect".
This is to ensure that we do not re-add functional
call backs.
// (instance, shouldSubscribe)
registerHubProxies(proxies, false);
});
proxies.ExampleChat = this.createHubProxy('ExampleChat');
proxies.ExampleChat.client = {};
proxies.ExampleChat.server = {
joinRoom: function (name, room) {
return proxies.ExampleChat.invoke.apply(proxies.
ExampleChat, $.merge(["JoinRoom"],
$.makeArray(arguments)));
},
sendMessage: function (name, message) {
return proxies.ExampleChat.invoke.apply(proxies.
ExampleChat, $.merge(["SendMessage"],
$.makeArray(arguments)));
},
sendMessageToRoom: function (name, room, message) {
return proxies.ExampleChat.invoke.apply(proxies.
ExampleChat, $.merge(["SendMessageToRoom"],
$.makeArray(arguments)));
}
};
return proxies;
};
signalR.hub = $.hubConnection("/signalr", { useDefaultPath:
false });
$.extend(signalR, signalR.hub.createHubProxies());
}(window.jQuery, window));
Powyżej nie został oczywiście przedstawiony cały zawarty tam kod. Jedy-
nie elementy, na które chciałbym zwrócić uwagę. Na początku uświadommy
sobie, co tak naprawdę się tutaj znajduje. Jest to samo-wywołująca się funk-
cja (javascript self invoking function). Zamieszczam angielską nazwę z dwóch
względów. Po pierwsze, tłumaczenie na polski niektórych nazw technicznych
wychodzi strasznie, i to jest zdecydowanie jeden z takich przypadków. Po dru-
gie, jeżeli ktoś nie rozumie, jak to działa, to bez problemu będzie wiedział,
czego szukać w Internecie.
Co do wewnętrznej budowy kodu, to spójrzmy na dwa miejsca. Po pierw-
sze, na funkcję createHubProxy.W jej argumencie jest podana nazwa, którą
to narzuciliśmy naszemu Hub-owi. Po drugie, na to, gdzie znajdują się napisa-
ne przez nas metody. Zostały one zamknięte w obiekcie, jako wartości unikal-
nych kluczy, a obiekt ten jest przypisany do Proxy naszego Hub-a. Jak łatwo
można było się domyśleć, wszystkie one zostały jak najbardziej prawidłowo
uznane za metody serwerowe.
Na koniec tego artykułu mam jeszcze prośbę, aby każdy przeanalizował
sobie resztę kodu Hub-a. Można dzięki temu zdobyć sporo ciekawej wiedzy
na temat szczegółów jego działania.
PODSUMOWANIE
Artykuł ten był pierwszą z dwóch części omawiania technologii SignalR.
Dowiedzieliśmy się, czym w ogóle są aplikacje czasu rzeczywistego, na jakiej
zasadzie działają oraz jak omawiana technologia odpowiada na ten sektor
potrzeb. Jeżeli chodzi o praktykę, to stworzyliśmy część serwerową naszego
rozwiązania, z którą będziemy, jako klienci, łączyć się w następnym artykule.
Ja ze swojej strony bardzo dziękuję za czas poświęcony na przeczytanie
tego artykułu i zapraszam do lektury kolejnych. W przypadku jakichkolwiek
uwag,pytańlubpropozycjipomysłównakolejneartykułyproszępisaćnakarol.
rogowski@gmail.com lub szukać mnie na https://twitter.com/KarolRogowski.
Karol Rogowski karol.rogowski@gmail.com
Absolwent Informatyki Politechniki Białostockiej. Microsoft Certificated Professional Deve-
loper .NET Web Developer. Obecnie pracuje jako Development Lead w firmie DevCore.Net.
Autor wielu treści na portalach technologicznych, głównie związanych z HTML 5 i JavaScript.
W wolnym czasie pokerzysta amator
22 / 10 . 2013 . (17) /
PROGRAMOWANIE APLIKACJI WEBOWYCH
Michał Leszczyński
N
ajpopularniejszą metodą logowania w Internecie jest uwierzytel-
nianie za pomocą hasła. Metoda ta, choć jest jedną z najwygod-
niejszych, nie jest pozbawiona wad. W celach porównawczych na
serwerze muszą być przechowywane hasła wszystkich użytkowników – naj-
częściej w formie hasha, np. z funkcji SHA1, bcrypt etc. W przypadku wycie-
ku bazy danych będącego choćby następstwem włamania, atakujący może
posłużyć się różnymi technikami, aby odzyskać oryginalne hasła, inwestując
w to odpowiednią ilość mocy obliczeniowej. Istnieje też ryzyko wstawienia
przez włamywacza backdoora w kodzie aplikacji, który zajmie się rejestro-
waniem haseł przesyłanych na serwer otwartym tekstem podczas logowa-
nia (ruch HTTPS trafiający do aplikacji zostaje już wcześniej odszyfrowany
przez serwer).
Odporność na tego typu zagrożenia wykazuje autoryzacja przy pomo-
cy certyfikatu użytkownika SSL, podczas której na serwer nigdy nie jest
wysyłany pełny certyfikat, a jedynie dowód na to, że użytkownik, który
go prezentuje, jest równocześnie jego właścicielem. Jest to możliwe dzię-
ki zastosowaniu kryptografii asymetrycznej. Po stronie serwera nie trzeba
więc przechowywać żadnych wrażliwych danych logowania dotyczących
konkretnych użytkowników. Bezpieczeństwo całego systemu przekłada
się bezpośrednio na bezpieczeństwo klucza używanego do wystawiania
certyfikatów.
Podpis cyfrowy
Algorytmy szyfrowania asymetrycznego, oprócz swojego typowego za-
stosowania w szyfrowaniu wiadomości, znajdują użycie przy tworzeniu pod-
pisów cyfrowych. Para kluczy dla szyfru asymetrycznego składa się z dwóch
kluczy: prywatnego (który należy do właściciela i powinien być przecho-
wywany bezpiecznie) oraz publicznego. Dowolna wiadomość może zostać
podpisana cyfrowo przez posiadacza klucza prywatnego, a wiarygodność
podpisu można zweryfikować, wykorzystując klucz publiczny.
SPOSÓB DZIAŁANIA
Wystawianie certyfikatów
Certyfikaty SSL użytkownika mogą być wydawane przez określony urząd
certyfikacji (CA), który posiada swój certyfikat główny i jest uznany za zaufa-
ny na serwerze aplikacji. Ponieważ certyfikaty użytkownika są wystawiane w
celu umożliwienia serwerowi sprawdzenia tożsamości klienta, a nie odwrot-
nie jak w przypadku klasycznego zastosowania SSL, certyfikat główny nie
musi być zainstalowany w systemie klienta.
Certyfikaty użytkownika SSL
– jak to ugryźć?
Technologia SSL znajduje swoje użycie w olbrzymiej ilości aplikacji i usług interne-
towych. Jednym z głównych celów jej zastosowania jest umożliwienie klientowi
sprawdzenie, czy komunikuje się on z zaufanym serwerem. Istnieje jednak rozsze-
rzenie, które pozwala dokonać zupełnie odwrotnej czynności, umożliwiając serwe-
rowi sprawdzenie autentyczności klienta. Celem tego artykułu jest zatem omówie-
nie i implementacja certyfikatów użytkownika na przykładzie aplikacji hostowanej
w kontenerze Tomcat.
Rysunek 1. Procedura wystawiania certyfikatów użytkownika SSL
Distinguished name
CertyfikatyużytkownikasązgodnezestandardemX.509(RFC5280
[1]
),
muszą więc zawierać distinguished name (DN) podmiotu oraz wystawcy,
czyli informacje o nich zapisane w formacie par atrybut=wartość, od-
dzielanych przecinkiem.
Przykładowy DN podmiotu:
CN=someguy123, O=Example Flail Store, OU=Member
Najczęściej używane standardowe atrybuty:
O organization name
OU organizational unit name
CN common name
L locality name
ST state or province
C country name
Uwierzytelnianie użytkownika
Autoryzacja użytkownika za pomocą certyfikatu jest opcjonalną częścią
SSL handshake, czyli negocjacji bezpiecznego połączenia z serwerem. Należy
tu zauważyć, że przeprowadzenie takiej autoryzacji nie jest możliwe w połą-
czeniu nieszyfrowanym.
Podczas uwierzytelniania certyfikatem użytkownika, losowe dane wy-
generowane podczas negocjacji bezpiecznego połączenia są podpisywane
przez użytkownika za pomocą wcześniej wystawionego mu certyfikatu. Pod-
pis ten jest później wysyłany wraz z informacjami o certyfikacie do serwera.
24 / 10 . 2013 . (17) /
PROGRAMOWANIE APLIKACJI WEBOWYCH
Do tagu Connector odnoszącego się do connectora HTTPS należy dodać
następujące atrybuty:
truststoreFile=""
truststorePass=""
clientAuth="want|true"
Atrybut clientAuth określa zachowanie serwera podczas negocjacji bez-
piecznego połączenia. Jeśli wartość atrybutu zostanie ustawiona na want, ser-
wer będzie honorował certyfikaty użytkownika, ale pozwoli również ustanowić
połączenie klientom, którzy z jakiegoś powodu nie mogą przedstawić prawi-
dłowego certyfikatu. W przypadku ustawienia wartości na true, serwer każ-
dorazowo będzie zrywał połączenia od klientów, którzy się nie uwierzytelnią.
CLIENT-SIDE: GENEROWANIE ŻĄDAŃ
CERTYFIKACJI Z PRZEGLĄDARKI
Do bezpiecznego przeprowadzenia certyfikacji potrzebne jest API, któ-
re pozwoli na wygenerowanie pary kluczy i stworzenie żądania certyfikacji
(CSR). Przeglądarki kompatybilne z Netscape (Firefox, Chrome, etc.) oferują
do tego celu tag keygen [3]
będący regularnym elementem formularza. Mi-
crosoft odmówił jednak implementacji tego rozwiązania w Internet Explorer,
ponieważ w systemach Windows Vista i nowszych dostępne jest Certificate
Enrollment API [4]
, którego można użyć przez ActiveX z poziomu skryptu po
stronie klienta.
Wobec tego, trzeba stworzyć aplikację, która zależnie od przeglądarki
klienta zaserwuje mu formularz wykorzystujący kompatybilną technologię.
Ze względu na ograniczoną ilość miejsca, implementacja omówiona w arty-
kule będzie dosyć uproszczona, aby nie zagłębiać się w rzeczy mocno wykra-
czające poza temat.
Po stronie klienta przykład ograniczy się do dwóch statycznych stron z
formularzami – jednym dla IE, drugim dla przeglądarek kompatybilnych z
Netscape. Oba formularze będą zawierały pole do wpisania nicku, który zo-
stanie później użyty jako Common Name (CN) w wygenerowanym certyfika-
cie, oraz kontrolkę generatora kluczy.
Keygen
Element reprezentuje generator pary kluczy i jest wyświe-
tlany w przeglądarce analogicznie do tagu
25/ www.programistamag.pl /
CERTYFIKATY UŻYTKOWNIKA SSL – JAK TO UGRYŹĆ?
Wynikowy formularz powinien wyglądać tak:
Listing 1. Formularz netscape.html dla przeglądarek kompatybil-
nych z Netscape
Przy próbie wysłania formularza żądanie certyfikacji zostanie automa-
tycznie wygenerowane i wstawione jako parametr csr. W odpowiedzi na to
zapytanie, serwer powinien wysłać wystawiony certyfikat wraz z nagłówkiem
Content-Type: application/x-x509-user-cert
Przeglądarka automatycznie zainstaluje taki certyfikat w swoim
magazynie.
CertEnroll
Certificate Enrollment API to rozbudowany interfejs od Microsoft,
który pozwala również na wystawianie żądań certyfikacji w formacie
PKCS#10 oraz instalowanie wygenerowanego certyfikatu na kompu-
terze klienta. Poprzez ActiveX z interfejsu można skorzystać za pomocą
X509EnrollmentWebClassFactory[5]
. Należy jednak pamiętać, że
przeglądarka ze względów bezpieczeństwa nie pozwoli odwołać się do
tego obiektu, jeśli strona z korzystającym z niego skryptem nie została po-
brana przez HTTPS.
Pora na stworzenie formularza dla IE (plik ie.html). Pożądane byłoby, aby
oba formularze miały podobny układ i wygląd. Wygląd tagu moż-
na emulować, używając
10/2013 (17) www•programistamag•pl Cena 9.90 zł (w tym VAT 23%) Index: 285358 Certfikaty SSLThere is no app Arduino a sprawa wyświetlaczy • ASP.NET SignalR • Budowanie wiedzy w zespole. Główne błędy i strategie OpenGL 2D Jak one działają i jak to za- implementować w Javie Koncepty stojące za filo- zofią platformy Android Programowanie grafiki: o shaderach i teksturach Twitter Bootstrap Co nowego w wersji 3
4 / 10 . 2013 . (17) / REDAKCJA/EDYTORIAL Nowe wydanie Programisty po raz siedemnasty gości już na Waszych półkach i czytnikach e-booków i ciągle nie brakuje w naszym miesięczni- ku ambitnych tematów. Lekturę numeru proponujemy zacząć od artykułu Łukasza Mazura nt. szybkiego i efektywnego tworzenia frontendów z użyciem frameworka Twitter Bootstrap. Artykuł ten stanowi kontynuację artykułu z poprzed- niego numeru Programisty. W tej części autor opisuje m.in. zmiany, któ- re pojawiły się w wersji 3.0, oraz wybrane komponenty, jakie możemy wykorzystać podczas tworzenia witryn. Następnie zachęcamy do łatwego do „przełknięcia” artykułu z zakresu tematyk miękkich. Michał Bartyzel i Mariusz Sieraczkiewicz opowiadają krótko o najczęstszych błędach podczas budowania wiedzy w zespole projektowym. Z kolei Sławomir Andrzejewski, codziennie pracujący nad zapewnieniem niezawodności sieci komórkowych, omawia dobre prak- tyki dotyczące przeprowadzania automatycznych testów akceptacyjnych. Ponadto polecamy artykuły naszych dwóch nowych autorów: teksty Mi- chała Charmasa będą traktować o zaawansowanych aspektach platfor- my Android, natomiast Rafał Jamróz krok po kroku podpowie, jak radzić sobie z utrzymaniem testów automatycznych. Na koniec kilka słów o następnym numerze Programisty. Wielkimi kroka- mi zbliża się rozszerzone wydanie grudniowe, a w nim znajdziecie szereg ciekawych, mamy nadzieję, tematów, na czele z „Bliżej Silikonu #2 – O analizie BIOS API, procesie ładowania jądra Windows, a także tworze- niu boot loadera dla własnego systemu”. Będzie to druga (i nie ostatnia) część cyklu autorstwa Gynvaela Coldwinda i Mateusza Jurczyka. Powiększone wydanie to również debiuty nowych autorów – Bartek Kuczyński zaproponuje temat „Vaadin 7 – naprawdę szybkie tworzenie aplikacji web w Javie”, a wszystkich amatorów elektroniki na pewno zain- teresuje artykuł Marka Klimowicza o robocie DIY reagującym na światło. Wkrótce w newsletterach, na WWW i Facebooku będziemy ujawniać więcej szczegółów na temat kolejnego wydania naszego magazynu. Tymczasem życzymy przyjemnej i owocnej lektury z poważaniem, Redakcja Wydawca: Anna Adamczyk annaadamczyk@programistamag.pl Redaktor naczelny: Łukasz Łopuszański lukaszlopuszanski@programistamag.pl Korekta: Tomasz Łopuszański Kierownik produkcji: Krzysztof Kopciowski bok@keylight.com.pl DTP: Krzysztof Kopciowski Dział reklamy: reklama@programistamag.pl tel. +48 663 220 102 tel. +48 604 312 716 Prenumerata: prenumerata@programistamag.pl Współpraca: Michał Bartyzel Mariusz Sieraczkiewicz Artur Machura Marek Sawerwain Łukasz Mazur Rafał Kułaga Sławomir Sobótka Michał Mac Gynvael Coldwind Bartosz Chrabski Michał Leszczyński Adres wydawcy: Dereniowa 4/47 02-776 Warszawa Druk: ArtDruk – www.artdruk.com ul. Napoleona 4 05-230 – Kobyłka Nakład: 4500 egz. * Redakcja zastrzega sobie prawo do skrótów i opracowań tekstów oraz do zmiany planów wydawniczych tj. zmiany w zapowiadanych tematach artykułów i terminach publikacji, a także nakładzie i objętości czasopisma. O ile nie zaznaczono inaczej, wszelkie prawa do wszystkich materiałów zamieszczanych na łamach magazynu Programista są zastrzeżone. Kopiowanie i rozpowszechnianie ich bez zezwolenia jest wzbronione. Naruszenie praw autorskich może skutkować odpowiedzialnością prawną, określoną w szczególności w przepisach ustawy o prawie autorskim i prawach pokrewnych, ustawy o zwalczaniu nieuczciwej konkurencji i przepisach kodeksu cywilnego oraz przepisach prawa prasowego. Redakcja magazynu Programista nie ponosi odpowiedzialności za szkody bezpośrednie i pośrednie, jak również za inne straty i wydatki poniesione w związku z wykorzystaniem informacji prezentowanych na łamach magazynu Programista. Wszelkie nazwy i znaki towarowe lub firmowe występujące na łamach magazynu są zastrzeżone przez odpowiednie firmy. Magazyn Programista wydawany jest przez Dom Wydawniczy Anna Adamczyk
SPIS TREŚCI BIBLIOTEKI I NARZĘDZIA Twitter Bootstrap – szybkie tworzenie witryn HTML. Co nowego w wersji 3..... Łukasz Mazur 6 ASP.NET SignalR – czyli aplikacje czasu bardzo rzeczywistego............................... Karol Rogowski 18 PROGRAMOWANIE APLIKACJI WEBOWYCH Certyfikaty użytkownika SSL – jak to ugryźć?.............................................................. Michał Leszczyński 28 PROGRAMOWANIE GRAFIKI Szybka grafika 2D: Shadery i tekstury........................................................................... BartoszTaudul 32 PROGRAMOWANIE SYSTEMÓW OSADZONYCH Arduino a sprawa wyświetlaczy......................................................................................... Marek Sawerwain 42 TESTOWANIE I ZARZĄDZANIE JAKOŚCIĄ Automatyczne testy akceptacyjne w procesie Continuous Delivery.......................... Sławomir Andrzejewski 52 LABORATORIUM BOTTEGA Zaawansowane programowanie na platformie Android. Część I: There is no app – kluczowe koncepty stojące za filozofią platformy Android... Michał Charmas 56 Refaktoryzacja testów legacy w kierunku wykonywalnych specyfikacji. Część I: Podstawowy refaktoring testów......................................................................... Rafał Jamróz 60 PLANETA IT Java nad Wisłą..................................................................................................................... Łukasz Sobótka 68 KLUB LIDERA IT Budowanie wiedzy w zespole. Główne błędy i strategie............................................... Michał Bartyzel, Mariusz Sieraczkiewicz 70 KLUB DOBREJ KSIĄŻKI Programowanie. Teoria i praktyka z wykorzystaniem C++...................................... Rafał Kocisz 72 Domain-Driven Design: Tackling Complexity in the Heart of Software................ Sławomir Sobótka 74 Zamów prenumeratę magazynu Programista bezpośrednio u nas przez formularz na stronie http://programistamag.pl/typy-prenumeraty/ lub zrealizuj ją na podstawie faktury Pro-forma. W spawie faktur Pro-Forma prosimy kontktować się z nami przez e-mail redakcja@programistamag.pl. Prenumerata realizowana jest też przez RUCH S.A: Zamówienia na prenumeratę w wersji papierowej i na e-wydania można składać bezpośrednio na stronie www.prenumerata.ruch.com.pl Ewentualne pytania prosimy kierować na adres e-mail: prenumerata@ruch.com.pl lub kontaktując się z Telefonicznym Biurem Obsługi Klienta pod numerem: 801 800 803 lub 22 717 59 59 – czynne w godzinach 7:00 – 18:00 (koszt połączenia wg taryfy operatora).
6 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA Łukasz Mazur SŁOWEM WSTĘPU ... Dzisiaj Internet jest bardzo ważnym medium, w którym można znaleźć większość potrzebnych nam informacji. Podstawowym składnikiem Interne- tu są strony i witryny www. Są one wizytówkami firm, blogów, poradników czy różnych portali. Ważne jest, aby były one estetyczne i intuicyjne dla użyt- kownika. Do ich budowy w większości używamy języka HTML w połączeniu z arkuszem stylów CSS, które są interpretowane przez przeglądarkę i wyświe- tlane na ekranie urządzenia (już nie tylko komputerów). Responsywne strony Obecnie wiele osób korzysta z urządzeń przenośnych takich jak: smartfony, tablety czy ultrabooki, gdzie wielkość ekranu jest inna niż na komputerze typu desktop (czy na laptopach). Aby strona wyświetlała się na tego typu urządzeniach prawidłowo,możnaużyćdobudowywitrynyframeworkaTwitterBootstrap.Możli- wośćtworzeniaresponsywnychstroninternetowychorazdodatkowewsparciedla wielu gotowych rozwiązań czyni ten framework niezwykle przydatnym. O Bootstrapie ... Kilka słów przypomnienia o frameworku Twitter Bootstrap. Jest to narzędzie mające ułatwić pracę developerom aplikacji webowych. Pozwala ono na łatwe i szybkie tworzenie aplikacji w oparciu o standardy CSS i JavaScript. Powstał z po- trzeby eliminacji problemów związanych z interfejsem graficznym tworzonych aplikacji w firmie Twitter. Początkowo próbując rozwiązać te problemy, develo- perzy korzystali z wielu wzajemnie niekompatybilnych bibliotek. Aby temu za- pobiec, inżynierowie współpracujący z serwisemTwitter zdecydowali się opraco- wać jeden, kompleksowy i w pełni spójny zestaw narzędzi developerskich. W gruncie rzeczy Twitter Bootstrap to zestaw bibliotek CSS. Tym, co wy- różnia go od podobnych rozwiązań, jest jego architektura. Framework oparty został o elastyczny preprocesor LESS. Uzyskamy dzięki temu szereg przydat- nych funkcji, m.in: • możliwość zagnieżdżania deklaracji, • operacje oraz funkcje koloru itp. PonadtoTwitter Bootstrap jest bardzo łatwy do wdrożenia, a kompilacji LESS można dokonać, używając np. JavaScript. Po kompilacji pakietów, Twitter Boot- strap zawiera jedynie czysty CSS bez zbędnych dodatków, takich jak obrazy czy kod JavaScript. Gwarantuje to szybkość działania oraz wysoki komfort użycia. W poprzedniej części omówiono pobieranie, instalacje oraz uruchomie- nie podstawowej strony wykonanej przy użyciu Twitter Bootstrap. W tej czę- ści postaramy się przedstawić kilka wybranych komponentów (w tym opisać bardziej szczegółowo tworzenie tabel oraz wykorzystanie karuzeli), które z Twitter Bootstrap – szybkie tworzenie witryn HTML. Co nowego w wersji 3 OmówieniewybranychelementówwTwitterBootstrap W pierwszej części artykułu wyjaśniliśmy, jak zacząć przygodę z Twitter Bootstrap. Nato- miast w tej części postaramy się przybliżyć ciekawsze jego elementy. Zaprezentowane zostaną takie składniki jak wybrane komponenty, elementy JavaScript'u, w tym ich za- stosowanie oraz finalnie responsive design. Dodatkowo opiszemy, co nowego pojawiło się w wersji v3.0.0, czyli jakich zmian można się spodziewać w najnowszej odsłonie. pewnością wzbogaca naszą witrynę, oraz dodatkowo zestawione będą waż- niejsze zmiany, które wystąpiły w wersji v3.0.0. TWITTER BOOTSTRAP V3.0.0 – ZMIANY W drugą rocznicę releasu Twitter Bootstrap, dostarczono jego wersję v3.0.0. Dla autorów zapewne to była szalona, długa i mozolna praca, ale final- nie produkt jest już dostępny. Wszyscy, którzy wzięli udział w testowaniu wer- sji RC (beta) oraz zgłaszali błędy czy także ulepszali kod, otrzymali od autorów wielkie i szczere podziękowania. Bardzo ciężko było by opracować tego typu narzędzie bez wsparcia społeczności. Nowy Bootstrap Niestety, już na samym początku potrzeba powiedzieć, żeTwitter Bootstrap v3.0.0 może wprowadzić obecnych użytkowników w lekkie zakłopotanie, a szczególnie za sprawą re-designu. Po gruntownym przeglądnięciu wprowa- dzonych zmian można stwierdzić, że najświeższe wydanie może nie być naj- lepsze dla wszystkich. Kiedy tylko przyjrzymy się dokumentacji, bez problemu zauważymy, że wybrane aspekty kodu zostały sporo zmienione. W tym przy- padku raczej nie jest to najlepszym rozwiązaniem (generalnie w softwarze wy- chodzi to zazwyczaj na plus). Jednak teraz będziemy zmuszeni do pewnego ro- dzaju przebudowy naszych aplikacji (czy też stron www) w próbie ewentualnej migracji do nowej wersji. Główna, podstawowa struktura pozostała praktycznie bez zmian. Jedynym wyjątkiem jest opcjonalna możliwość dodania responsyw- nych elementów dla przeglądarki Internet Explorer 8 (Listing 1). Listing1.SzablonpodstawowejstrukturystronyzwykorzystaniemBootstrap
Hello, world!
7/ www.programistamag.pl / TWITTER BOOTSTRAP – SZYBKIE TWORZENIE WITRYN HTML Została sporo zmieniona praca grid systemu, o czym później. Również do- myślnie mamy włączony tryb responsive i nie ma już potrzeby, aby decydo- wać, czy dołączyć bootstrap-responsive.less, oczywiście jest także możliwość jego wyłączenia. Teraz można wybierać pomiędzy klasami, jak .col-sm dla małych gridów czy .col-lg dla dużych. Oznacza to, że można dokładniej precyzować, jak witryna będzie działać na smartfonach i tabletach, w przeci- wieństwie do komputerów stacjonarnych. Używając kodu: div.sidebar { make-column(3); } możemy utworzyć elementy zachowujące się jak kolumny, mimo że same nie mają znaczników elementu. Twitter Bootstrap nie wspiera już domyślnie starych przeglądarek. Jeżeli jednak koniecznie chcemy włączyć możliwie najstarszy tryb zgodności dla IE, powinniśmy w meta tagach witryny dodać następujący wpis:Nieco bliżej szczegółów Nadal są wykorzystywane ikony ze zbioru Glyphicons, które zostały od- świeżone i odrestaurowane. Można stwierdzić, że największym zmianom zo- stał poddany grid system Bootstrapa. W dokumentacji widnieją nowe nazwy klas CSS. Wprawiają one w lekkie zakłopotanie, jednak przy dłuższej pracy z nimi nabierają dosyć logicznego sensu. Nie zmienia to jednak faktu, że tego typu zmiany mogą wprowadzić niemało zamieszania i wymusić "przestawie- nie się" na nowe nazewnictwo. Na szczęście wszelkie widoczne poprawki typograficznych elementów nie zostały wprowadzone. Możemy cieszyć się tekstem (przynajmniej w skompilowanej wersji) rodem z Twitter Bootstrap 2.3.2. Formularze i buttony należą do grupy elementów, które zyskały nowy świeży wygląd, jednym się to spodoba, innym przeciwnie (flat design). Najświeższe trendy wyolbrzymiają większość elementów, jednak ogromne inputy tekstowe są mało poręczne. Drugą zmianą w designie jest usunięcie wypukłości z kolorowych buttonów. O ile te z poprzedniej wersji były całkiem ładne, to w tej chwili stały się trochę monotonne i jednokolorowe. JavaScrip- t'owe dodatki pozostały w większości bez zmian. Oczywiście poprawiono ich design, który jednym jak zwykle przypadnie do gustu, a innym już nie. Gene- ralnie należy zwrócić również uwagę na dwojakie spojrzenie przez autorów Twitter Bootstrap. Z jednej strony stawiają na minimalizm (płaskie buttony), a z drugiej wciąż pozostawiono cienie wielu elementów – można postawić tu małe pytanie: czy takie częściowo sprzeczne działania razem dobrze się komponują? Podsumowanie zmian Dla tych, którzy nie mieli okazji śledzić bieżących zmian, oto krótkie zesta- wienie tych ważniejszych, które wystąpiły w Bootstrap v3.0.0: • Nowy design oraz opcjonalne motywy: w wersji v3.0.0 postawiono na pła- ski flat design. Jak twierdzą autorzy, to nie jest tendencja – to wszystko po to, aby ulepszyć możliwości dostosowywania. Uproszczona została estetyka wyglądu, gdzie opcjonalny wybór tematu będzie z pewnością pomocny. • Mobilne urządzenia na plan pierwszy (zawsze responsywne): prawie wszystko zostało przeprojektowane i przebudowane, tak aby rozpocząć od urządzeń przenośnych i skalować projekt w górę. • Nowy Customizer: narzędzie zostało przeprojektowane, teraz elementy są zgromadzone w przeglądarce zamiast w bazie Heroku. Posiada lepszą obsługę zależności i dodatkowo ma wbudowaną obsługę błędów. Teraz wygodniej możemy zapisać preferencje jako anonimowy gest dla łatwego ponownego ich wykorzystania, udostępniania czy modyfikacji. • Lepszy domyślny box model: wszystko w Bootstrap przyjmuje teraz box-sizing: border-box, co dostarcza możliwości łatwiejszego dosto- sowania rozmiaru i lepszej manipulacji w rozbudowanym grid systemie. • Super-powered grid system: z czterema poziomami klas siatki, odpo- wiednio dla: telefonów, tabletów, komputerów stacjonarnych i dużych komputerów stacjonarnych. • Przepisane wtyczki JavaScript: wszystkie zdarzenia obecnie znajdują się w przestrzeni nazw, rzeczy no-conflict działają teraz o wiele lepiej i efektowniej. • Ikony Glyphicons: przywrócono Glyphicons do głównego repozytorium. W wersji 2.x występowały jako obrazki, teraz są one w formacie czcionki i obejmują 40 nowych glifów. • Zregenerowany pasek nawigacyjny: teraz jest on zawsze responsive i został wyposażony w kilka przydatnych komponentów. • Elementy modalne są bardziej elastyczne: przeprowadzono remont tej części kodu, aby elementy były bardziej responsywne na urządzeniach mobilnych. Teraz można przewijać obszar renderowania zamiast wcze- śniej ustawionego sztywno max-height. • Usunięto wybrane składniki: odrzucony został accordion (zastąpiono go składanymi panelami), submenu oraz wpisywanie znaków z wyprzedzeniem. • Bardziej spójne klasy: przyciski, tabele, formularze, alerty i inne zostały zaktualizowane, po to aby uzyskać bardziej spójne klasy dla łatwiejszego konfigurowania i rozszerzalności. • Dodano nową dokumentację: nie tylko dla komponentów, ale dotyczą- ce także wsparcia przez przeglądarki (w tym pułapek i różnych błędów), najczęściej zadawane pytania FAQ odnośnie licencji, wsparcia dla kompo- nentów third party oraz odnośnie dostępności. • Odrzucony support dla Internet Explorer 7 i Firefox 3.6: dla Internet Explorer 8 potrzeba dołączyć Respond.js dla wszystkich Media Queries w celu pracy w pełnym zakresie. Dla osób testujących prerelease i innych, które posiadają jeszcze wersję RC, poniżej zestawiona została lista niektórych z bardziej znaczących zmian wprowadzonych do RC: • Zostały naprawione błędy zgłoszone w wersji RC, • Odrestaurowano Glyphicons, • Komponenty NavBars teraz wymagają .navbar-default dla wersji standardowej, • Panele teraz wymagają .panel-default dla standardowej (szarej), • Alerty wymagają teraz klasę modyfikującą (np. .alert.alert-warning – dla domyślnego wcześniej żółtego alertu), • Wiele responsywnych narzędzi może być zastosowanych do tego samego elementu, • Przykłady są z powrotem w głównym repozytorium i zostały w pełni zaktualizowane, • Błędy kompilacji Customizera zostały naprawione, • Dodano opcjonalne motywy, • Jumbotrony są teraz wykonane w taki sposób, aby przedłużyć szerokość obszaru wewnątrz kontenera. Odwracając to, spowodujemy, iż jumbotron w kontenerze zostanie zaokrąglony i wcięty. Rysunek 1. PrzykładJumbotronu • Składniki NavBar zostały usprawnione z uwagi na obecność kontenerów i innych elementów. • Można zobaczyć kilka nowych modyfikacji w marginesach i wcięciach, ale zmiana znaczników nie powinna być do tego wymagana.
8 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA WYBRANE KOMPONENTY Kolejno zostanie zaprezentowanych kilka ważniejszych (ciekawszych) komponentów, wchodzących w skład frameworka. W sekcji Bootstrapa (Com- ponents) zgromadzono podstawowe style dla elementów interfejsu, takich jak karty z treścią, panele nawigacyjne, paski postępu, przyciski, okienka komunikatów (informacyjne, ostrzegawcze, błędów), nagłówki itp. Podczas budowy naszej strony jest niezmiernie przydatnym, iż mamy tyle rzeczy do wykorzystania niewielkim nakładem pracy – czy wręcz za darmo. Postaramy się krótko zaprezentować kilka wybranych komponentów (ze względu na dużą ich ilość nie sposób przedstawić wszystkich, więc w celu dokładnego przejrzenia zachęcam do odwiedzenia strony Bootstrapa). Komponenty zostały przedstawione na Rysunkach od 2 do 8. Kod użyty do ich wyświetlenia zamieszczono na Listingach od 2 do 8. Rysunek 2. Przykład dostępnych różnych typów alertów Listing 2. Definiowanie alertów
...
...
...
TABELE Przejdźmy teraz do opisu tabel. Jak wiemy, tabele bardzo często znajdują swoje zastosowanie w wielu biznesowych rozwiązaniach. Twitter Bootstrap posiada kilka klas, które umożliwiają ich dostosowywanie, a także zapewniają estetyczny wygląd. Podstawowa tabela Tabele tworzymy poprzez HTMLowy znacznik10 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA Listing 13. Zmniejszenie dopełnienia wewnątrz tabeli
Zapis data-target="#carousel-example-generic" musi prowadzić do nazwy naszej karuzeli. A ilość wpisów w znaczniku
1and1.pl NOWE DOMENY NOWE MOŻLIWOŚCI DOMENY | E-MAIL | STRONY WWW | HOSTING | SERWERY Teraz w ofercie 1&1 mamy już ponad 700 nowych domen najwyższego poziomu (nTLD). Stwórz chwytliwy adres, np. nowak.shop, serwis.auto lub winiarnia.online i używaj go jako głównej lub dodatkowej domeny dla Twojego serwisu. Będziesz jeszcze lepiej widoczny w Internecie! W 1&1 zarejestrowaliśmy już około 20 milionów domen, co czyni nas największym europejskim rejestratorem. Dzięki funkcji przekierowania, z łatwością połączysz zarejestrowaną u nas domenę ze swoją stroną internetową, nawet jeśli jest ona hostowana przez inną firmę. Więcej informacji na 1and1.pl TERAZ REZERWUJ ZA DARMO I BEZ ZOBOWIĄZAŃ!* *Wstępna rezerwacja nTLD jest bezpłatna i nie gwarantuje, że domena zostanie zarejestrowana. O przyznawaniu wstępnie zarezerwowanych nTLD decydują niezależne od 1&1 rejestry domen. Więcej informacji na 1and1.pl oraz w regulaminach rejestrów domen.
12 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA Listing 19. Kolejny obrazek zamknięty w znaczniku div
Podołączeniuopisówdoslajdównaszkodbędziesięprezentowałnastępująco: Listing 20. Dołączenie opisów do slajdówThis is description
for first element
This is description
for second element
This is description
for third element
13/ www.programistamag.pl / TWITTER BOOTSTRAP – SZYBKIE TWORZENIE WITRYN HTML Listing 25. Przykład rozwijanego menu
Modal title
One fine body…
14 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA Musimy dołączyć jQuery, Twitter Bootstrap CSS i dwa pliki JavaScript – je- den dla komponentu tooltip Twitter Bootstrap i jeden dla popover Twitter Bootstrap. Plik JavaScriptu popover jest dostępny w folderze JS z pakietu Twitter Bootstrap jako bootstrap-popover.js oraz plik JavaScriptu dla tooltip jest dostępny w folderze JS jako bootstrap-tooltip.js. JQuery jest dostępny pod docs/assets/js jako jquery.js, lub może wskazywać na ten URL: http://code.jqu- ery.com/jquery-1.10.2.min.js. Popovery w grupach przycisków i grupach wejść wymagają specjalnych ustawień. Podczas korzystania z popoverów na elementach .btn-group lub .input-group, będziemy musieli określić opcję .container:'body', aby uniknąć niepożądanych efektów ubocznych (takich jak szersze elementy lub utrata zaokrąglonych rogów, gdy popover jest wyzwalany). Dostępne są cztery opcje umiejscowienia: top, right, bottom i wyrów- nanie do lewej left. Ze względu na aspekty wydajności, API dla tooltip'ów i popover'ów są typu option-in. Jeśli chcemy ich używać, potrzebujemy określić więc opcję selektora. Poniżej zostaną wymienione poszczególne opcje uruchamiające komponent. • $().popover(options). • $('#element').popover('show') – pokazuje popover dla elementu. • $('#element').popover('hide') – ukrywa popover dla elementu. • $('#element').popover('toggle') – przełącza popover dla elementu. • $('#element').popover('destroy') – usuwa popover dla elementu. Rysunek 12. Przykład popoverów Przykład: $('#myPopover').on('hidden.bs.popover', function () { // do something }) Rysunek 13. Przykład tooltipów Podobnie jak popovery – tooltipy w grupach przycisków i grupach wejść wymagają specjalnych ustawień. Podczas korzystania z tooltipów na ele- mentach .btn-group lub .input-group będziemy musieli określić opcje .container:'body'', aby uniknąć niepożądanych efektów ubocznych (ta- kich jak szersze elementy lub utrata zaokrąglonych rogów, gdy tooltip jest wyzwalany). Opcje dla poszczególnych tooltipów można alternatywnie okre- ślić z wykorzystaniem atrybutów danych, jak pokazano poniżej: Użycie wewnątrz znacznika:Hover over mePoszczególne opcje uruchamiające komponent: • $().tooltip(options). • $('#element').tooltip('show') – pokazuje tooltip dla elementu. • $('#element').tooltip('hide') – ukrywa tooltip dla elementu. • $('#element').tooltip('toggle') – przełącza tooltip dla elementu. • $('#element').tooltip('destroy') – usuwa tooltip dla elementu. Przykład: $('#myTooltip').on('hidden.bs.tooltip', function () { // do something }) RESPONSIVE WEB DESIGN Responsive Web Design jest funkcjonalnością zapewniającą użytkow- nikowi uzyskanie najlepszych odczuć (user experience) podczas przeglą- dania stron internetowych na różnych urządzeniach (posiadających różne rozmiary). Na przykład, w przypadku przeglądania strony internetowej na monito- rze komputera, a następnie wyświetlania jej na smartfonie (gdzie rozmiar jest mniejszy niż rozmiar monitora komputera), nie powinna występować większa różnica podczas pracy z UI. Inaczej mówiąc, powinniśmy mieć złudzenie, iż jesteśmy w tym samym serwisie (miejscu). Chcąc uzyskać tego typu wrażenia, potrzeba na takiej stronie uaktywnić elementy odpowiedzialne za mecha- nizm responsive design. Aby testować zachowanie strony, można zmieniać rozmiar przeglądarki za pomocą zmiany rozmiaru okien. Pomocnym będzie wtedy rozszerzenie Window Resizer dla przeglądarek Chrome czy Firefox. Jak działa responsive design? Do pracy z responsive design potrzeba stworzyć CSS, który zawiera style odpowiednie dla różnych urządzeń o róż- nych zakresach rozmiarów. Gdy strona ma się załadować na konkretnym urządzeniu, za pomocą różnych technik front-endu jak kwerendy mediów (Media Queries – które pozwalają dostosować styl do dokumentu oparty na środowisku, w którym dokument ten jest renderowany), wielkość obszaru wyświetlania musi zostać wykryta, po czym specyficzny styl dla urządzenia jest ładowany. Przejdźmy teraz nieco w głąb Responsive Design CSS początkowo opie- rając się na przykładzie wcześniejszej wersji Bootstrapa v2.3.2. Weźmy pod uwagę integrację 'bootstrap-responsive.css' z naszą stroną i postarajmy się zro- zumieć, w jaki sposób działanie tego mechanizmu zostało osiągnięte. Na wstępie musimy pamiętać, iż potrzeba dodać następujący wiersz we- wnątrz sekcji head naszej strony internetowej:Meta tag viewport jest powszechnie używany, jako że zastępuje on do- myślny i pomaga załadować styl związany z konkretnym obszarem wyświe- tlania. Właściwość width ustawia szerokość ekranu. Może ona zawierać war- tości numeryczne jak 320, oznaczając 320 pikseli, lub może posiadać wartość 'device-width', która informuje przeglądarkę, aby skorzystać z natywnej rozdzielczości (lub szerokości – dla uproszczenia) urządzenia. Właściwość initial-scale jest początkową skalą obszaru wyświetlania jako mnożnik. Tak więc, gdy jest ustawiona na 1.0, to oznacza wtedy natywną szerokość dla danego urządzenia. Oczywiście, po tym należy dodać responsive CSS z Boot- strap, jak pokazano na poniższym kodzie:Teraz, gdy spojrzymy na plik responsive CSS, możemy zauważyć, że po deklaracji pewnych ogólnych składników (linie ~10 do 22) istnieją wyspecy- fikowane różne sekcje zaczynające się od znacznika '@media'. Mamy tam zdefiniowane style dla różnych wielkości urządzeń:
MISSION CODE ACHIEVE NEW LEVEL JOIN THE CREW
16 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA • Pierwsza z tych sekcji rozpoczyna się od znacznika '@media (max- width: 480px)', który określa style dla urządzeń, gdzie maksymalna szerokość jest równa 480 pikseli. • Druga sekcja rozpoczyna się od znacznika '@media (max-width: 767px)', który określa style dla urządzeń, gdzie maksymalna szerokość jest równa 767 pikseli. • Trzecia sekcja rozpoczyna się od znaczników '@media (min-width: 768px) oraz (max-width: 979px)', zapis ten określa style dla urzą- dzeń, których minimalna szerokość wynosi 768 pikseli, a maksymalna szerokość to 979 pikseli. • Następna sekcja jest określona dla urządzeń z maksymalną szeroko- ścią 979 pikseli, więc zaczyna się od znacznika '@media (max-width: 979px)'. • Ostatnie dwie sekcje zaczynają się od znaczników '@media (min- width: 980px)' oraz '@media (min-width: 1200px)', więc są prze- znaczone dla urządzeń o minimalnej szerokości 980 pikseli i 1200 pikseli. Funkcją, jaką spełnia ten arkusz, jest więc przechowywanie stylów według minimalnej i maksymalnej szerokości urządzeń korzystających z właściwości 'min-width' oraz 'max-width'. Aby układ responsive mógł być osiągnię- ty, Twitter Bootstrap wykonuje kolejno trzy rzeczy: 1. Modyfikuje szerokości kolumny w siatce. 2. Ilekroć jest wymagane, używa stosu elementów zamiast elementu pływającego, Element główny (html) tworzy korzeń kontekstu układania. Inne kontek- sty układania są generowane przez umieszczanie kolejnych elementów (w tym elementów pozycjonowanych relatywnie) o wyliczonej wartości 'z-in- dex' innej niż 'auto'. 3. Aby renderować prawidłowo nagłówki i tekst, zmienia ich rozmiary w ra- zie potrzeby. NARZĘDZIARESPONSYWNEWWERSJI3.0.0 W dzisiejszych czasach coraz więcej osób przegląda strony www za pomocą różnych urządzeń mobilnych. Praktycznie każdy nowoczesny telefon czy tablet umożliwia w jakimś stopniu korzystanie z Internetu. Jako projektanci musimy zadbać o to, aby zapewnić takim osobom jak najłatwiejszy dostęp do treści i funkcjonalności witryny. Prawidłowe dostosowanie strony do urządzeń mo- bilnych sprawi, że szerokie grono osób będzie mogło ją wygodnie przeglądać. Projektowanie stron na przeglądarki mobilne nie jest łatwym zadaniem.To zło- żony temat, który obejmuje zarówno aspekty wizualne, jak i funkcjonalne. W celu szybszego rozwoju interfejsów wspierających zastosowania mo- bilne (mobile-friendly), potrzeba korzystać z klas użytkowych służących do pokazywania/ukrywania zawartości poprzez urządzenia, wykorzystując Me- dia Queries. Szybsze rozwijanie takich interfejsów jest możliwe dzięki Twitter Bootstrap, który teraz również posiada zestaw klas użytkowych dla przyśpie- szenia tego procesu. Klasy te są dostępne w module 'responsive-utilities.less'. Należy używać ich w ograniczonym zakresie, unikając tworzenia różnych wersji tej samej witryny (w celu uzupełnienia prezentacji dla każdego urzą- dzenia). Narzędzia responsywne są obecnie dostępne tylko w blokach i w przełączeniu tabeli (block and table toggling). Korzystanie z nich inline oraz jako elementów tabeli nie jest aktualnie obsługiwane. Można wykorzystać jedną klasę lub kombinacji dostępnych klas w celu przełączania zawartości w bieżących wartościach granicznych obszaru wyświetlania. Warto opanować najważniejsze techniki responsywne, czyli takie, które po- zwolą nam dostosować witrynę do różnych urządzeń. Poznać podstawowe zasa- dy tworzenia witryn responsywnych, dowiedzieć się, jak wykorzystać możliwości Media Queries oraz jak stworzyć płynny układ kolumn. Poznać przydatne rozwią- zania, umożliwiające dostosowanie typowych elementów strony, jak: obrazki, tabele oraz menu do mobilnych przeglądarek. Framework Bootstrap oferuje sze- roki zestaw klas i skryptów, które pozwolą łatwo i szybko stworzyć responsywną strukturę witryny, dodać style oraz różne przydatne funkcjonalności. Rysunek 14. Ilustracja obrazująca filozofię Responsive Design
17/ www.programistamag.pl / TWITTER BOOTSTRAP – SZYBKIE TWORZENIE WITRYN HTML Rysunek 15. Zestawienie klas dla przełączania zawartości bieżącego obszaru wyświetlania w wersji 3.0.0 PODSUMOWANIE W drugiej części artykułu omówiono wybrane ważniejsze (z punktu wi- dzenia developera) komponenty będące składnikami frameworka. Opisano również ważniejsze zmiany występujące w wersji v3.0.0, która jest oficjalną wersją produkcyjną. Twitter Bootstrap obecnie implementuje flat design, co w przypadku stron internetowych nie zawsze jest pożądane. Wystąpiły pew- ne zmiany w nazewnictwie oraz strukturze i teraz nie wszystko, co było do- stępne w v 2.3, jest dostępne także w v3.0.0. Zmiana niektórych nazw klas być może ma sens, ale utrudnia aktualizację do najnowszej wersji. Można pokusić się o ponowną kompilację plików LESS, przywracając poprzednie nazewnic- two, ale będzie to pracochłonne. Podsumowując – dzięki wykorzystaniu bibliotek Bootstrap'a rozwijane aplikacje internetowe tworzone są szybciej, będą się cechowały skalowalno- ścią oraz przyjaznym interfejsem użytkownika. Bezbłędne działanie pakietu jest zagwarantowane przez twórców w przeglądarkach Chrome, Safari oraz Firefox. Można zaznaczyć, że wciąż trwają także prace nad polepszeniem wy- dajności obsługi dla przeglądarki Internet Explorer. Zdobytą wiedzę możemy bez przeszkód zastosować do utworzenia wła- snej witryny oraz poszerzyć swoje umiejętności w zakresie tworzenia este- tycznie wyglądających, responsywnych stron. Dzięki Bootstrapowi proces ten będzie łatwy i przyjemny. Koniec z wyliczaniem marginesów, tworzeniem form czy ramek od podstaw – Twitter Bootstrap zrobi to za nas. Korzystając ze skalowalności, nasza strona będzie dobrze wyglądała na komputerze, ta- blecie czy smartfonie. Wykorzystanie frameworka przy projektowaniu strony przyspieszy nam pracę oraz zwiększy zadowolenie z efektu końcowego. W sieci PP http://twitter.github.com/bootstrap/–zasobyTwitterBootstrapv2.3.2. PP http://themecrunch.com/2013/04/twitter-bootstrap-tutorials-tools- and-resources/ – zasoby oraz tutoriale dlaTwitter Bootstrap. PP http://getbootstrap.com/components/ – dokumentacja dla komponentówTwitter Bootstrap v3.0.0. PP http://getbootstrap.com/css/ – dokumentacja modułu CSS dla Twitter Bootstrap v3.0.0. PP http://getbootstrap.com/javascript/ – dokumentacja JavaScript dla Twitter Bootstrap v3.0.0. PP http://www.bootstraptor.com/bootstrap3 – zestawy szablonów i motywy zbudowane przy wykorzystaniuTwitter Bootstrap v3.0.0. PP http://www.w3resource.com/twitter-bootstrap/responsive-design.php– ResponsiveWebDesignprzywykorzystaniuTwitterBootstrap–artykuł. PP http://getbootstrap.com/customize/ – moduł pobierania frameworka wraz z panelem personalizowania. PP http://getbootstrap.com/getting-started/#migration – ważniejsze zmiany pomiędzy wersjami 2.x a 3.0.0. PP http://bradfrostweb.com/blog/web/mobile-first-responsive-web- design/ – blog traktujący o tematyce Responsive Design Łukasz Mazur lukash.mazur@gmail.com Autor obecnie jest programistą/architektem aplikacji biznesowych dedykowanych na platformy mobilne. Pracuje dla irlandzkiej firmy Mobile Travel Technologies Ltd. Dodatkowo poszerza swoja wiedzę dotyczącą zagadnień analityki biznesowej w Institute of Technology Blanchardstown – Dublin na wydziale Computing Business Intelligence & Data Mining.
18 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA Karol Rogowski S koro już wiemy, czym są aplikacje czasu rzeczywistego, a jeszcze nie zdążyliśmy przejść do żadnej konkretnej rozmowy technicznej, to zasta- nówmy się, czy faktycznie jest tego aż tak wiele, żeby było warto zaprzą- tać sobie tym głowę. Zacznijmy może od portali społecznościowych, które to ostatnio na całym świecie zdobywają coraz większą popularność. Nie mówię już nawet o kwestiach rozmów, ponieważ konieczność dostawania tam danych na żywo jest kwestią bezdyskusyjną. Zauważmy też, że każda niemalże akcja innych użytkowników mająca z nami jakiś związek skutkuje natychmiastowym poinformowaniem nas o tym. Portale społecznościowe nie są oczywiście jedy- ne, jeżeli chodzi o konieczność posiadania świeżych danych. Spójrzmy na przy- kład na wszelkiego typu notowania. Czy to giełdowe czy też związane z wy- nikami sportowymi. Dodatkowo są też najróżniejsze aplikacje pozwalające na jednoczesną interakcję ze sobą kilku użytkowników.Tak, wiem, że pierwszą na- chodzącą myślą są gry interaktywne, ale to nie jest jedyny przykład. Są przecież też sytuacje, gdy jednocześnie musimy pracować nad jakimś dokumentem. Przykłady tego typu można by mnożyć jeszcze długo. Ale mam nadzieję, że udało mi się już zobrazować skalę problemu posiadania realnych danych oraz to, że naprawdę istnieje szeroki rynek na tego typu rozwiązania. PUSH SERVICE Zanim zaczniemy omawiać konkretne rozwiązanie technologiczne, po- wiedzmy sobie, w jaki sposób odbywa się komunikacja w omawianych apli- kacjach. Bazuje ona na wzorcu zwanym Push Service. I chociaż bardzo się starałem, to nie udało mi się wymyśleć tłumaczenia na polski, które nie wy- paczałoby treści zawartej w oryginalnej nazwie. Dlatego właśnie zostaniemy przy nazwie anglojęzycznej. Push Service, najogólniej mówiąc, ma za zadanie dostarczanie i rozdzielanie komunikatów. Przyjrzyjmy się rysunkowi poniżej, a następnie omówimy dokładniejszą budowę tego wzorca. Rysunek 1. Budowa wzorca Push Service Jak widzimy powyżej Push Service opiera się na synchronizacji współ- pracy podpiętych do niego klientów oraz zdarzeń. Klienci w tym przypadku powinni być rozumiani jako wszelkiego rodzaju aplikacje chcące korzystać z powiadomień dostarczanych przez serwis. Z drugiej strony mamy natomiast zdarzenia, których wystąpienie powoduje wysłanie powiadomień do odpo- wiednich klientów. Natomiast klienci po otrzymaniu powiadomienia już po swojej stronie odpowiednio na nie reagują. Wiem, że na pewno taki schemat nie zobrazuje od razu wszystkiego, ale na pewno da jakiś pogląd na to, co chcemy osiągnąć. SIGNALR Na początku powiedzmy sobie, czym w ogóle jest SignalR. Jest to Frame- work pozwalający nam na tworzenie Push Service-ów. Składa on się z dwóch części. Pierwszą z nich jest zestaw rozwiązań serwerowych, które służą nam do faktycznego budowania tego, w jaki sposób ma wyglądać nasz serwis, oraz z części klienckiej. Odpowiedzialna jest ona za możliwość komunikacji z serwisem. Dzięki odpowiednim bibliotekom pozwala ona na komunikację z praktycznie każdą platformą. Jest to bardzo ważne, ponieważ ciężko jest wy- magać, aby wszystko pracowało na .NET-cie. Ogólna idea działania tej technologii jest poniekąd schowana w jej na- zwie. Chodzi mianowicie o to, że powinniśmy operować na sygnałach. Po- przez sygnał rozumiemy wysłanie małej porcji danych, która zostaje już po stronie odczytującej ją aplikacji odpowiednio zinterpretowana. Powinniśmy się wystrzegać przesyłania przy użyciu SignalR całych dużych kawałków da- nych. Jeżeli chcemy napisać sygnał, który będzie informował o zmianach w którymś z elementów wyświetlanych na naszej stronie, powinno to się odbyć następująco: Sygnał informuje nas o tym, że dany element się zmienił. Może to zrobić na przykład poprzez wysłanie jego identyfikatora. Dopiero nasza aplikacja po odpowiedniej interpretacji sygnału pobiera oddzielnym zapyta- niem nowe dane i obsługuje je na właściwy sposób. NAPISZMY COŚ Jak już pewnie zdążyliście zauważyć, w swoich artykułach staram się kłaść możliwie jak największy nacisk na praktyczne wykorzystanie technologii i w ten sposób zapoznawać Was z jej działaniem. Nie inaczej będzie w tym przypadku. Napiszemy Push Service, który to będzie obsługiwał scenariusz prostego chatu. Nie jest to może jakiś bardzo skomplikowany i wyrafinowa- ny przykład, ale pozwoli zaznajomić się ze sposobem działania omawianej technologii. A jeżeli ktoś będzie chciał dalej się tego uczyć, to będzie miał już gotowe podwaliny. Pierwszym krokiem, jaki należy wykonać, jest utworzenie pustej aplika- cji ASP.NET MVC4, na której będziemy pracować. Kolejną czynnością będzie dodanie do naszego projektu Hub-a. Hub jest to klasa, w której będziemy ASP.NET SignalR – czyli aplikacje czasu bardzo rzeczywistego Aplikacje czasu rzeczywistego to rozwiązania, które dostarczają dane na bieżąco. Powiedzmy na przykład, że chcemy przeczytać sobie poranne wiadomości na którymś z licznych istniejących w sieci portali. Dane powinny tam być możliwie świeże, z tym że nie są one raczej dostarczane na żywo, a po prostu pobierają się podczas naszego wej- ścia na stronę. Wszystko w tej sytuacji jest ok, ponieważ nie oczekujemy chyba odświe- żania ich co chwilę. Inaczej sytuacja wygląda, jeżeli chodzi np. o chat na jakimś portalu społecznościowym. Tutaj otrzymywanie danych na żywo jest kwestią krytyczną.
19/ www.programistamag.pl / ASP.NET SIGNALR – CZYLI APLIKACJE CZASU BARDZO RZECZYWISTEGO definiować zachowania naszego serwisu. Będą się tam znajdować zarówno wymagane zdarzenie, jak i te metody, które są charakterystyczne tylko dla naszego rozwiązania. Klasę taką możemy dodać, jako jeden z już przygoto- wanych elementów. Rysunek 2. Dodawanie nowego Hub-a Po kliknięciu przycisku Add do naszego projektu zostanie dodany nowy element. Oprócz tego, że widzimy teraz nowy plik, to warto zwrócić uwagę na trzy nowe referencje, które pojawiły się w naszym rozwiązaniu. Są to bibliote- ki Microsoft.AspNet.SignalR.Core, Microsoft.AspNet.SignalR.Owin oraz Micro- soft.AspNet.SignalR.SystemWeb. Jak łatwo można zgadnąć, są to elementy odpowiedzialne za działanie technologii SignalR w naszej aplikacji. Zajrzyjmy teraz do naszego nowego pliku. Listing 1. Zawartość pliku ChatHub.cs namespace ExampleChat { using Microsoft.AspNet.SignalR; ////// Klasa huba naszego projektu
/// public class ChatHub : Hub
{
public void Hello()
{
Clients.All.hello();
}
}
}
Widzimy, że nowoutworzona klasa ma tak naprawdę bardzo prostą budo-
wę. Jedynym elementem, na jaki należy w tym momencie zwrócić uwagę, jest
jej dziedziczenie po klasie Hub. Co z tego dziedziczenia wynika, zobaczymy
już za chwilę.
Zanim jednak przejdziemy do implementacji funkcjonalności, musimy
poinformować aplikację, że będzie ona korzystała z hub-ów. Robimy to pod-
czas zdarzenia startu aplikacji. Możemy oczywiście znaleźć je w pliku Global.
asax. Zarejestrowanie hub-ów musi odbyć się od razu po wywołaniu akcji
RegisterAllAreas(). Jest to bardzo ważne, ponieważ w przeciwnym wy-
padku nasze rozwiązanie w ogóle nie zadziała.
Listing 2. Prawidłowa rejestracja Hub-ów w pliku Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteTable.Routes.MapHubs();
WebApiConfig.Register(GlobalConfiguration.
Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.
Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
Skoro nasza aplikacja już wie, że ma korzystać z hub-ów, zastanów się te-
raz, jakie w ogóle funkcjonalności chcemy zaimplementować. Po pierwsze,
musi być możliwość wysyłania wiadomości. Fajnie też by było móc nadać
sobie jakieś imię. Funckjonalnością jakby oczywistą jest możliwość otrzymy-
wania informacji. Jako bonus dajmy naszemu rozwiązaniu odrobinę prywat-
ności. Powiedzmy, że damy użytkownikom możliwość spotykaniu się w poko-
jach i rozmawiania tylko wewnątrz nich. To byłoby chyba na tyle, jeżeli chodzi
o opcje. Jeśli jeszcze jakaś nasunie się w trakcie, to będziemy uzupełniać tę
listę na bieżąco.
Wszystkie te zdarzenia należy zakodować oczywiście w naszym Hub-ie.
Może zróbmy to w ten sposób, że zaprezentuję od razu gotowy i, wydaje mi
się, dość czytelnie okomentowany kod, a następnie będę omawiał kolejne
elementy i w ten sposób tłumaczył, co tam się dzieje.
Listing 3. Zaprogramowana klasa Hub-a
/// /// Klasa Hub-a naszego chat-u
/// [HubName("ExampleChat")]
public class ChatHub : Hub
{
/// /// Metoda pozwalająca na wysłanie wiadoności do
wszystkich użytkowników
/// /// Nazwa użytkownika/// Treść wiadomościpublic void SendMessage(string name, string message)
{
var msg = string.Format("{0}: {1}", name, message);
Clients.All.newMessage(msg);
}
/// /// Metoda pozwalająca na połączenie to jakiegoś pokoju
/// /// Nazwa użytkownika/// Nazwa pojoku to którego chcemy
podączyćpublic void JoinRoom(string name, string room)
{
Groups.Add(Context.ConnectionId, room);
var msg = string.Format("{0} joined room: {1}", name,
room);
Clients.Group(room).newMessage(msg);
}
/// /// Metoda pozwalająca na wysłanie wiadoności do
użytkowników w danym pokoju
/// /// Nazwa użytkownika/// Nazwa pokoju/// Treść wiadomościpublic void SendMessageToRoom(string name, string room,
string message)
{
var msg = string.Format("{0}: {1}", name, message);
Clients.Group(room).newMessage(msg);
}
/// /// Nadpisane zdarzenie na łączenie się z Hub-em
/// /// Obiekt odpowiedni dla metody którą
nadpisuje public override Task OnConnected()
{
this.SendMonitoringData("Połączono", Context.
ConnectionId);
20 / 10 . 2013 . (17) / BIBLIOTEKI I NARZĘDZIA return base.OnConnected(); } ////// Nadpisane zdarzenie na rozłączenie się z Hub-em
/// /// Obiekt odpowiedni dla metody którą
nadpisuje public override Task OnDisconnected()
{
this.SendMonitoringData("Rozłączono", Context.
ConnectionId);
return base.OnDisconnected();
}
/// /// Nadpisane zdarzenie na ponowne połączenie się z
Hub-em
/// /// Obiekt odpowiedni dla metody którą
nadpisuje public override Task OnReconnected()
{
this.SendMonitoringData("Połączono ponownie",
Context.ConnectionId);
return base.OnReconnected();
}
/// /// Metoda pozwalająca na informaowanie użytkowników o
zdarzeniach występujących na Hub-ie
/// /// Rodzaj zdarzenia/// Identyfikator połączenie
które wywołało to zdarzenieprivate void SendMonitoringData(string eventType, string
connection)
{
Clients.All.newEvent(eventType, connection);
}
}
Tak jak obiecałem, tak też teraz zrobię. Skoro każdy już przeczytał zapre-
zentowany kod, możemy przejść do szczegółowego omawiania go. Pierw-
szym elementem, jaki rzuca nam się w oczy, jest atrybut HubName; pozwala
on na ustawienie nazwy naszego Hub-a. Do czego konkretnie może się to
przydać, zobaczymy w kolejnym listingu. W pełni natomiast zrozumiemy to
podczas kolejnego artykułu, gdy będziemy pisać klientów rozmawiających
na czacie.
Pierwszą publiczną metodą jest SendMessage. Pozwala ona na wysłanie
wiadomości do wszystkich podłączonych klientów. Właśnie w tym momen-
cie chciałbym, abyśmy zobaczyli, jak wygląda komunikacja z klientami. Po
pierwsze, omawiana właśnie metoda musi być wywołana przez klienta. Jak
on to robi, będzie wyjaśnione w kolejnej części artykułu. W tym momencie in-
teresuje nas kontakt od serwera do klienta. W tym przypadku chcemy wysłać
sygnał do wszystkich klientów. Dlatego właśnie z obiektu Clients skorzystali-
śmy z właściwości All, która to oczywiście zwraca nam wszystkich klientów.
Następnie już sami, bez żadnych podpowiedzi, definiujemy metodę oraz pa-
rametry, które zostaną wysłane do klientów ze zbioru All. Kolejną metodą jest
JoinRoom.Tak jak już mówliśmy, każdy potrzebuje czasami odrobiny prywat-
ności. Dlatego właśnie SignalR oferuje nam możliwość wysyłania sygnałów
tylko do klientów będących w pewnej grupie. Właśnie za to odpowiada nasza
metoda. Na początku widzimy kod, który dodaje identyfikator połączenia, z
którego została wywołana ta metoda do pokoju o nazwie przekazanej para-
metrem. Na końcu, tak jak poprzednio, wysyłamy wiadomość do odpowied-
nich klientów. Z tym, że tym razem nie są to już wszyscy klienci, a jedynie
ci należący do tego pokoju (do tej grupy). Zrobiliśmy to poprzez wywołanie
na obiekcie Clients metody Group, zamiast właściwości All. Kolejna przedsta-
wiona metoda daje nam możliwość wysłania wiadomości tylko do klientów z
danej grupy. Nie ma tu żadnych nowych konstrukcji, jeżeli chodzi o kod, nie
będziemy więc się na niej zatrzymywać.
Kolejne trzy kroki będzie stanowić nadpisanie zdarzeń z klasy bazowej.
Jest to bardzo charakterystyczne zachowanie, jeżeli chodzi o programowanie
obiektowe, dlatego też, jeżeli ktoś ma problem ze zrozumieniem tej części
kodu, to zachęcam do douczenia się. Wiedza ta na pewno się przyda. Co do
zawartości tych metod, to każda z nich zawiera odwołanie do metody, która
to ma monitorować aktywności na naszym Hub-ie. Następnie oczywiście wy-
wołujemy nadpisane zdarzenie z klasy bazowej, dzięki czemu działanie naszej
aplikacji nie zostanie zachwiane.
Ostatnim elementem stworzonym w klasie jest metoda pozwalająca na
obronienie monitorowanych akcji. W przypadku realnej aplikacji w tym miej-
scu znajdowałby się prawdopodobnie kod w jakiś sposób monitorujący za-
chodzące zdarzenie. Jako że jest to aplikacja demonstracyjna, to będziemy
po prostu wysyłać informacje o zdarzeniach do wszystkich podłączonych
klientów.
Skoro mamy już wszystko przygotowane, to uruchommy naszą aplikację i
zobaczmy, co się stanie. Chwila napięcia….
No i nie stało się nic, a na pewno nic pozytywnego. Otrzymaliśmy ekran
błędu mówiący, że poszukiwane zasoby nie zostały odnalezione. Nie ma czym
się martwić, bo ten ekran jest dokładnie tym, co powinniśmy w tym momen-
cie widzieć. Zastanówmy się, co tak naprawdę oczekiwaliśmy, że zobaczymy.
Jakiś napis typu:„Nie masz żadnych kontrolerów ani widoków, ale nie martw
się, wszystko na pewno działa”? Niestety nie jest tak pięknie.
Rysunek 3.Widok aplikacji po uruchomieniu
Skoro teraz widzimy błąd, to pozostaje pytanie, jak sprawdzić, czy apli-
kacja faktycznie działa. Dla nas działanie aplikacji oznacza ni mniej ni więcej
niż to, że działa nasz Hub-a. Możemy to sprawdzić pod poniższym adresem:
http://localhost:58033/signalr/hubs. Jeżeli wszystko zaprogramowaliśmy po-
prawnie, to powinniśmy zobaczyć w ekranie przeglądarki kod Hub-a, którego
w trakcie artykułu stworzyliśmy.
Listing 4. Kod działającego Hub-a
/*!
* ASP.NET SignalR JavaScript Library v1.0.0
* http://signalr.net/
*
* Copyright Microsoft Open Technologies, Inc. All rights
reserved.
* Licensed under the Apache 2.0
* https://github.com/SignalR/SignalR/blob/master/LICENSE.md
*
*/
/// /// (function ($, window) {
if (typeof ($.signalR) !== "function") {
throw new Error("SignalR: SignalR is not loaded. Please
ensure jquery.signalR-x.js is referenced before ~/
signalr/hubs.");
}
var signalR = $.signalR;
function makeProxyCallback(hub, callback) {
return function () {
// Call the client hub method
callback.apply(hub, $.makeArray(arguments));
};
}
$.hubConnection.prototype.createHubProxies = function () {
21/ www.programistamag.pl / ASP.NET SIGNALR – CZYLI APLIKACJE CZASU BARDZO RZECZYWISTEGO reklama var proxies = {}; this.starting(function () { // Register the hub proxies as subscribed // (instance, shouldSubscribe) registerHubProxies(proxies, true); this._registerSubscribedHubs(); }).disconnected(function () { // Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs. // (instance, shouldSubscribe) registerHubProxies(proxies, false); }); proxies.ExampleChat = this.createHubProxy('ExampleChat'); proxies.ExampleChat.client = {}; proxies.ExampleChat.server = { joinRoom: function (name, room) { return proxies.ExampleChat.invoke.apply(proxies. ExampleChat, $.merge(["JoinRoom"], $.makeArray(arguments))); }, sendMessage: function (name, message) { return proxies.ExampleChat.invoke.apply(proxies. ExampleChat, $.merge(["SendMessage"], $.makeArray(arguments))); }, sendMessageToRoom: function (name, room, message) { return proxies.ExampleChat.invoke.apply(proxies. ExampleChat, $.merge(["SendMessageToRoom"], $.makeArray(arguments))); } }; return proxies; }; signalR.hub = $.hubConnection("/signalr", { useDefaultPath: false }); $.extend(signalR, signalR.hub.createHubProxies()); }(window.jQuery, window)); Powyżej nie został oczywiście przedstawiony cały zawarty tam kod. Jedy- nie elementy, na które chciałbym zwrócić uwagę. Na początku uświadommy sobie, co tak naprawdę się tutaj znajduje. Jest to samo-wywołująca się funk- cja (javascript self invoking function). Zamieszczam angielską nazwę z dwóch względów. Po pierwsze, tłumaczenie na polski niektórych nazw technicznych wychodzi strasznie, i to jest zdecydowanie jeden z takich przypadków. Po dru- gie, jeżeli ktoś nie rozumie, jak to działa, to bez problemu będzie wiedział, czego szukać w Internecie. Co do wewnętrznej budowy kodu, to spójrzmy na dwa miejsca. Po pierw- sze, na funkcję createHubProxy.W jej argumencie jest podana nazwa, którą to narzuciliśmy naszemu Hub-owi. Po drugie, na to, gdzie znajdują się napisa- ne przez nas metody. Zostały one zamknięte w obiekcie, jako wartości unikal- nych kluczy, a obiekt ten jest przypisany do Proxy naszego Hub-a. Jak łatwo można było się domyśleć, wszystkie one zostały jak najbardziej prawidłowo uznane za metody serwerowe. Na koniec tego artykułu mam jeszcze prośbę, aby każdy przeanalizował sobie resztę kodu Hub-a. Można dzięki temu zdobyć sporo ciekawej wiedzy na temat szczegółów jego działania. PODSUMOWANIE Artykuł ten był pierwszą z dwóch części omawiania technologii SignalR. Dowiedzieliśmy się, czym w ogóle są aplikacje czasu rzeczywistego, na jakiej zasadzie działają oraz jak omawiana technologia odpowiada na ten sektor potrzeb. Jeżeli chodzi o praktykę, to stworzyliśmy część serwerową naszego rozwiązania, z którą będziemy, jako klienci, łączyć się w następnym artykule. Ja ze swojej strony bardzo dziękuję za czas poświęcony na przeczytanie tego artykułu i zapraszam do lektury kolejnych. W przypadku jakichkolwiek uwag,pytańlubpropozycjipomysłównakolejneartykułyproszępisaćnakarol. rogowski@gmail.com lub szukać mnie na https://twitter.com/KarolRogowski. Karol Rogowski karol.rogowski@gmail.com Absolwent Informatyki Politechniki Białostockiej. Microsoft Certificated Professional Deve- loper .NET Web Developer. Obecnie pracuje jako Development Lead w firmie DevCore.Net. Autor wielu treści na portalach technologicznych, głównie związanych z HTML 5 i JavaScript. W wolnym czasie pokerzysta amator
22 / 10 . 2013 . (17) / PROGRAMOWANIE APLIKACJI WEBOWYCH Michał Leszczyński N ajpopularniejszą metodą logowania w Internecie jest uwierzytel- nianie za pomocą hasła. Metoda ta, choć jest jedną z najwygod- niejszych, nie jest pozbawiona wad. W celach porównawczych na serwerze muszą być przechowywane hasła wszystkich użytkowników – naj- częściej w formie hasha, np. z funkcji SHA1, bcrypt etc. W przypadku wycie- ku bazy danych będącego choćby następstwem włamania, atakujący może posłużyć się różnymi technikami, aby odzyskać oryginalne hasła, inwestując w to odpowiednią ilość mocy obliczeniowej. Istnieje też ryzyko wstawienia przez włamywacza backdoora w kodzie aplikacji, który zajmie się rejestro- waniem haseł przesyłanych na serwer otwartym tekstem podczas logowa- nia (ruch HTTPS trafiający do aplikacji zostaje już wcześniej odszyfrowany przez serwer). Odporność na tego typu zagrożenia wykazuje autoryzacja przy pomo- cy certyfikatu użytkownika SSL, podczas której na serwer nigdy nie jest wysyłany pełny certyfikat, a jedynie dowód na to, że użytkownik, który go prezentuje, jest równocześnie jego właścicielem. Jest to możliwe dzię- ki zastosowaniu kryptografii asymetrycznej. Po stronie serwera nie trzeba więc przechowywać żadnych wrażliwych danych logowania dotyczących konkretnych użytkowników. Bezpieczeństwo całego systemu przekłada się bezpośrednio na bezpieczeństwo klucza używanego do wystawiania certyfikatów. Podpis cyfrowy Algorytmy szyfrowania asymetrycznego, oprócz swojego typowego za- stosowania w szyfrowaniu wiadomości, znajdują użycie przy tworzeniu pod- pisów cyfrowych. Para kluczy dla szyfru asymetrycznego składa się z dwóch kluczy: prywatnego (który należy do właściciela i powinien być przecho- wywany bezpiecznie) oraz publicznego. Dowolna wiadomość może zostać podpisana cyfrowo przez posiadacza klucza prywatnego, a wiarygodność podpisu można zweryfikować, wykorzystując klucz publiczny. SPOSÓB DZIAŁANIA Wystawianie certyfikatów Certyfikaty SSL użytkownika mogą być wydawane przez określony urząd certyfikacji (CA), który posiada swój certyfikat główny i jest uznany za zaufa- ny na serwerze aplikacji. Ponieważ certyfikaty użytkownika są wystawiane w celu umożliwienia serwerowi sprawdzenia tożsamości klienta, a nie odwrot- nie jak w przypadku klasycznego zastosowania SSL, certyfikat główny nie musi być zainstalowany w systemie klienta. Certyfikaty użytkownika SSL – jak to ugryźć? Technologia SSL znajduje swoje użycie w olbrzymiej ilości aplikacji i usług interne- towych. Jednym z głównych celów jej zastosowania jest umożliwienie klientowi sprawdzenie, czy komunikuje się on z zaufanym serwerem. Istnieje jednak rozsze- rzenie, które pozwala dokonać zupełnie odwrotnej czynności, umożliwiając serwe- rowi sprawdzenie autentyczności klienta. Celem tego artykułu jest zatem omówie- nie i implementacja certyfikatów użytkownika na przykładzie aplikacji hostowanej w kontenerze Tomcat. Rysunek 1. Procedura wystawiania certyfikatów użytkownika SSL Distinguished name CertyfikatyużytkownikasązgodnezestandardemX.509(RFC5280 [1] ), muszą więc zawierać distinguished name (DN) podmiotu oraz wystawcy, czyli informacje o nich zapisane w formacie par atrybut=wartość, od- dzielanych przecinkiem. Przykładowy DN podmiotu: CN=someguy123, O=Example Flail Store, OU=Member Najczęściej używane standardowe atrybuty: O organization name OU organizational unit name CN common name L locality name ST state or province C country name Uwierzytelnianie użytkownika Autoryzacja użytkownika za pomocą certyfikatu jest opcjonalną częścią SSL handshake, czyli negocjacji bezpiecznego połączenia z serwerem. Należy tu zauważyć, że przeprowadzenie takiej autoryzacji nie jest możliwe w połą- czeniu nieszyfrowanym. Podczas uwierzytelniania certyfikatem użytkownika, losowe dane wy- generowane podczas negocjacji bezpiecznego połączenia są podpisywane przez użytkownika za pomocą wcześniej wystawionego mu certyfikatu. Pod- pis ten jest później wysyłany wraz z informacjami o certyfikacie do serwera.
24 / 10 . 2013 . (17) / PROGRAMOWANIE APLIKACJI WEBOWYCH Do tagu Connector odnoszącego się do connectora HTTPS należy dodać następujące atrybuty: truststoreFile=""
truststorePass=""
clientAuth="want|true"
Atrybut clientAuth określa zachowanie serwera podczas negocjacji bez-
piecznego połączenia. Jeśli wartość atrybutu zostanie ustawiona na want, ser-
wer będzie honorował certyfikaty użytkownika, ale pozwoli również ustanowić
połączenie klientom, którzy z jakiegoś powodu nie mogą przedstawić prawi-
dłowego certyfikatu. W przypadku ustawienia wartości na true, serwer każ-
dorazowo będzie zrywał połączenia od klientów, którzy się nie uwierzytelnią.
CLIENT-SIDE: GENEROWANIE ŻĄDAŃ
CERTYFIKACJI Z PRZEGLĄDARKI
Do bezpiecznego przeprowadzenia certyfikacji potrzebne jest API, któ-
re pozwoli na wygenerowanie pary kluczy i stworzenie żądania certyfikacji
(CSR). Przeglądarki kompatybilne z Netscape (Firefox, Chrome, etc.) oferują
do tego celu tag keygen [3]
będący regularnym elementem formularza. Mi-
crosoft odmówił jednak implementacji tego rozwiązania w Internet Explorer,
ponieważ w systemach Windows Vista i nowszych dostępne jest Certificate
Enrollment API [4]
, którego można użyć przez ActiveX z poziomu skryptu po
stronie klienta.
Wobec tego, trzeba stworzyć aplikację, która zależnie od przeglądarki
klienta zaserwuje mu formularz wykorzystujący kompatybilną technologię.
Ze względu na ograniczoną ilość miejsca, implementacja omówiona w arty-
kule będzie dosyć uproszczona, aby nie zagłębiać się w rzeczy mocno wykra-
czające poza temat.
Po stronie klienta przykład ograniczy się do dwóch statycznych stron z
formularzami – jednym dla IE, drugim dla przeglądarek kompatybilnych z
Netscape. Oba formularze będą zawierały pole do wpisania nicku, który zo-
stanie później użyty jako Common Name (CN) w wygenerowanym certyfika-
cie, oraz kontrolkę generatora kluczy.
Keygen
Element reprezentuje generator pary kluczy i jest wyświe-
tlany w przeglądarce analogicznie do tagu
25/ www.programistamag.pl / CERTYFIKATY UŻYTKOWNIKA SSL – JAK TO UGRYŹĆ? Wynikowy formularz powinien wyglądać tak: Listing 1. Formularz netscape.html dla przeglądarek kompatybil- nych z Netscape
Przy próbie wysłania formularza żądanie certyfikacji zostanie automa- tycznie wygenerowane i wstawione jako parametr csr. W odpowiedzi na to zapytanie, serwer powinien wysłać wystawiony certyfikat wraz z nagłówkiem Content-Type: application/x-x509-user-cert Przeglądarka automatycznie zainstaluje taki certyfikat w swoim magazynie. CertEnroll Certificate Enrollment API to rozbudowany interfejs od Microsoft, który pozwala również na wystawianie żądań certyfikacji w formacie PKCS#10 oraz instalowanie wygenerowanego certyfikatu na kompu- terze klienta. Poprzez ActiveX z interfejsu można skorzystać za pomocą X509EnrollmentWebClassFactory[5] . Należy jednak pamiętać, że przeglądarka ze względów bezpieczeństwa nie pozwoli odwołać się do tego obiektu, jeśli strona z korzystającym z niego skryptem nie została po- brana przez HTTPS. Pora na stworzenie formularza dla IE (plik ie.html). Pożądane byłoby, aby oba formularze miały podobny układ i wygląd. Wygląd tagu