Webes felhasználói felületek
Konstantinusz Kft. © 2009
Tartalomjegyzék Bevezetés ........................................................................... 3 Felhasználói felületek általános jellemzői ................................3 Navigáció: .......................................................................... 7 Webes felületek hiányosságai ................................................9 Hogy tudok visszamenni? ........................................................10 Már megint kereshetem ki? .....................................................10 Most megint ki kell töltenem az egészet? ...................................11 Kérjük töltsön ki minden kötelező mezőt! ..................................11 Már tényleg csak 1 hiba van ....................................................12
Biztonsági problémák .........................................................13 User_id=1234 ........................................................................13 Kérem ne nyomkodja az F5-öt! ................................................14 Tisztelt <script>! ...................................................................15
Bevezetés Felhasználói felületek mára már elég kiforrottak lettek, sokszor annyira természetesek, hogy észre sem vesszük őket. Ez viszont webes felületekre gyakran nem igaz. Sajnos a webes környezet technikai korlátai miatt eleve hátránnyal indul az asztali alkalmazásokkal szemben. Weben kifejezetten kihívást jelenthet olyan dolgok megvalósítása, amit asztali alkalmazásoknál már készen kapunk. Az is észrevehető webes felületek esetén, hogy sok esetben nincs egy határozott koncepciójuk, még egy adott webes alkalmazáson belül sem. Minden egyes felületen mintha újra fel lenne találva a grafikus felületek ötlete. Ezen túl sokszor olyan primitív, idegesítő hiányosságaik vannak, hogy nehéz elhinni hogy ilyenek még vannak. Ezért a továbbiakban a felhasználói felületek általános áttekintése után a webes felületek leggyakoribb problémáit szeretném bemutatni és tanácsokat adni a megoldásukra, beleértve néhány biztonsági problémát is, amik bizonyos mértékben szintén a felületek megvalósításától függnek.
Felhasználói felületek általános jellemzői Ha általánosan akarjuk megközelíteni a felhasználói felületeket, akkor először azt kell tisztáznunk, hogy mi egy felület célja általánosságban. A válasz alapjában véve egyszerű és nem is meglepő: egy felület információt jelenít meg, és lehetőséget ad adatok bevitelére és műveletvégzésre. Ez azért fontos, mert ideális esetben ezek a funkciók egy adott felület esetében egy konkrét dologgal kapcsolatosak. Tehát mindig van egy meghatározott dolog, amivel kapcsolatban a felület információkat hivatott megjeleníteni, és ugyanezzel a dologgal kell, hogy kapcsolatos legyen a műveletvégzés és az adatbevitel is. Ez a felismerés azért lényeges, mert segít nekünk kategorizálni, rendszerezni hogy milyen felületekre lesz szükségünk, és hogy ezeknek a felületeknek mi lesz a feladata. Mint ahogy a programozásban is fontos, hogy egy-egy objektum vagy modul ne legyen túlterhelve felelősségekkel, úgy felületeknél is ez a helyzet. Egy olyan rendszerben, ahol sok felület van, amik különböző dolgokkal foglalkoznak, lényeges, hogy a felületek felelősségei ne legyenek keverve. Egy felület egyszerre csak egy dologgal és egy feladattal foglalkozzon. Természetesen helyenként szükség van a felületek együttműködésére, vagy arra a lehetőségre, hogy egyik felület kiegészíthesse a másik felület munkáját.
Nézzünk egy példát. Tegyük fel, hogy van egy rendszerünk, ami üzlethelyiségek bérbeadását kezeli. Egy helyiséggel kapcsolatosan kezelünk adatokat (alapterület, bérleti díj, elhelyezkedés, stb). A helyiségeket cégek bérlik, akiknek az adatait szintén a rendszerünkben kezeljük. Tehát itt két dolog van, amivel foglalkozik a rendszerünk, helyiségek és cégek. Ez a két dolog nem is független egymástól, mivel helyiséget bérlethet cég, és ezt be is kell tudnunk állítani.
Az egyik felület ezek kezelésére így nézhetne ki:
Ezen az egy felületen alapvetően minden ott van, ahol szeretnék. Igazából ez rendben is lenne, ha csak ennyi lenne az egész rendszer. A gond akkor kezdődik ha más dolgok is vannak a rendszerben, főleg olyanok, amikhez szintén cégeket lehet kötni. Ebben az esetben elég furcsa lenne, hogy a cég adatait a bérleti űrlapon kell szerkeszteni, vagy éppen több helyen is külön-külön, ami azért is rossz lenne, mert akkor több helyen is meg kellene valósítani a cég adatainak a szerkesztését, ami többszörözött kódot jelenthet.
A következő példa viszont elkülöníti a felelősségeket:
Ebben az esetben a bérlő cég adatait csak megjeleníti a felület, de nem itt kell szerkeszteni, hanem csak kiválaszthatom, esetleg azt is valamilyen másik felület segítségével. Így tehát a bérelhető helyiséggel is a neki szánt felület foglalkozik, és a céggel is, ami azt jelenti, hogy a céget hasonló módon hozzáköthetem más dolgokhoz is, amit akár ugyanazzal a segédfelülettel választhatok ki, így a felületek újrafelhasználhatósága is jelentősen megnő, amivel pedig a belefektetett munkaidő is csökken. Félreértés ne essék, ezeknél a példáknál nem azzal van a probléma, hogy egyszerre jelenik meg szerkesztőfelület a cégről és a helyiségről. Baj abból lesz, ha ezek programozás technikailag is egybe vannak megírva. Ha például külön van cég szerkesztő, és helység szerkesztő felület, viszont a helyiség szerkesztő felülete megjeleníti a cégszerkesztőt is, akkor nincs probléma, hiszen a cégszerkesztő attól még egy önálló felület, viszont hordozható (ami ráadásul még külön plusz pont). Tehát ezek az intelmek elsősorban a programozóknak szólnak, nem a designer-eknek. Tehát az imént látott felület két másikat hív segítségül. Egy listát és egy űrlapot. Ebben a tekintetben nem egyedi, ugyanis megfigyelhetjük, hogy a legtöbb dologhoz listák és űrlapok kellenek, hiszen ha több van belőle akkor látnom kell róla egy listát, és természetesen tudnom kell szerkeszteni és újat felvenni is. A listákat és űrlapokat szintén érdemes külön választani, mert nem csak egyben lehet rájuk szükségem.
Így mostmár van egy felület rendszerem, aminek minden egyes felülete csak egy dologgal és egy felelősséggel foglalkozik, és ezek a felületek csak együttműködnek valamilyen módszerrel (ezt később részletesen is megnézünk). Valójában egy teljes felület rendszert is meg lehet valósítani kizárólag listák és űrlapok koncepciójával, a trükk csak a felületek együttműködése és a navigáció lesz. Amit talán érdemes kiemelni a listáknál az a kereső, vagy egyéb szűrési lehetőség. Gyakori hiba, hogy a keresés módosításához meg kell nyomnom egy gombot annak érdekében hogy visszamehessek a kereső űrlapra. Ezeket érdemes úgy megcsinálni, hogy a kereséshez szükséges beviteli mezők és gombok mindig látszódjanak, és szintén ne vesszen el belőlük amit egyszer beírtunk vagy beállítottunk.
Tehát a felületeket igyekezzünk szétválasztani felelősségek és feladatok szerint amennyire csak lehet, és tegyük őket hordozhatóvá amennyire csak lehet. Hordozhatóság azt jelenti, hogy megjeleníthetem akárhol, és megnyithatom akárhonnan. Nyilván ez nem kötelező követelmény, hiszen technikailag is kihívást jelent, viszont nagyon nagy pozitívum, ami későbbiekben jelentősen megkönnyíti az ember munkáját.
Navigáció: Ha már feldaraboltuk a felületeinket felelősségek szerint, akkor a következő megoldandó kérdés a felületek közti navigáció, vagyis hogy hogyan jutunk egy egyik felületről a másikra. Megfigyelhetjük, hogy a legtöbb adminisztrációs jellegű tevékenység a felhasználó részéről egy
folyamat,
ami
meghatározott
felületeket
érint,
meghatározott
lépésekben
és
sorrendben. Egy-egy ilyen tipikus tevékenység lényegében egy útvonalat határoz meg a felületeken keresztül amit végig kell tudni járni. Éppen ezért fontos, hogy a felületek közti mozgás is kényelmesen működjön, és pontosan úgy juthasson el a felhasználó egyik felületről a másikra, ahogy és amikor azt igényli, anélkül hogy a folyamatot meg kelljen szakítania vagy újrakezdenie.
Megvalósításban alapvetően két fajta lehetőség van, az ablakok, és a lapozgatás. Az első viszonylag egyértelmű: ha el akarok jutni egyik felületről a másikra (például egy listából meg akarok nyitni egy elemet szerkesztésre), akkor az megnyílik egy új ablakban az előbbi felett vagy mellett. A lényeg, hogy mindkét felület egyszerre látható. A második lehetőség az, hogy amikor a következő felületre kell eljutnom, akkor az aktuálisat leváltja az új, így egyszerre csak egyet látok.
Az általában egyik esetben sem probléma, hogy egyik felületről megnyithassam a következőt. Viszont ami sokkal lényegesebb, hogy vissza is tudjak jutni oda ahonnan jöttem, anélkül hogy a korábbi felületek állapotai elvesznének. Ez az ablakos módszernél viszonylag egyértelmű, hiszen az előző felület nem tűnt el, legfeljebb csak eltakarta az újabb. Szóval ha bezárok egy ablakot, akkor ott lesz alatta (vagy mellette valahol) az előző. Ugyanez a lapozgatásnál már nem olyan egyértelmű. A leggyakoribb hiba, amit elkövetnek a fejlesztők, hogy nem lehet egy adott felületről visszajutni az előzőre. Ez főleg webes alkalmazásoknál fordul elő, mivel ott technikai adottságai miatt a lapozgatós módszer a jellemző. A hátránya ennek a hiányosságnak az, hogy a felhasználónak így gyakran újra kell kezdenie egy folyamatot, ha félúton szeretne visszajutni ez előző felületre. A továbbiakban nézzük meg tehát a webes felületek leggyakoribb problémáit, és hogy mit érdemes tenni ellenük.
Webes felületek hiányosságai
Mint az előző fejezetben említettük, az egyik legjellemzőbb probléma a hiányos navigáció. Alapvetően weboldalakon a böngésző nyújt navigációs lehetőséget, ezért ott nem is nagyon kell foglalkozni vele. Ez viszont csak addig működik, amíg a megjelenítendő felületet, és annak állapotát az URL határozza meg. Ez nem minden esetben vagy így, gyakorlatilag onnantól kezdve, hogy az ember űrlapokat is kezd használni, már nem csak az URL határozza meg, hogy mikor mit látok. Továbbá vannak olyan helyzetek, ahol az URL-t használni nem is lehet, technikai korlátai miatt. Komolyabb
rendszereknél
felületrendszernek,
mivel
pedig az
részletesebben is foglalkozunk).
nem
is
biztonsági
ajánlatos
az
problémákat
URL is
alapján
okozhat
működnie
(ezzel
a
később
Hogy tudok visszamenni? Gyakran előfordul, hogy egész egyszerűen hiányzik az előző felületekre visszalépés. Tehát az első jó tanács: tegyünk "vissza" gombot az oldalainkra! A probléma megoldása persze nem ilyen egyszerű. Ahhoz, hogy vissza tudjunk menni az előző oldalra, tudnunk kell, hogy mi az előző oldal. Ha pedig visszatértünk az előző oldalra, akkor tudnunk kell, hogy mi az azelőtti, és így tovább. Ehhez meg kell valósítani a hívási lánc tárolását. A hívási lánc tárolja minden korábbi felületről azt az információt, ami a felületet azonosítja, és lehetővé teszi hogy újra megjeleníthessem, méghozzá abban az állapotban ahogy otthagytam! A hívási láncot nyilván valahol tárolni is kell. Ezt megtehetnénk az URL-be, hidden input mezőkbe, és a session adatokba is. Az első kettő ezekből annyi hátránnyal indul, hogy a kliens oldalon is láthatóak és manipulálhatóak, ezért biztonsági problémát jelenthetnek. Ezért személy szerint a session-t tartom a legrátermettebbnek, mivel egy adminisztrációs felületnek nem kell könyvjelzőzhetőnek lennie, viszont illik biztonságosra csinálni.
Már megint kereshetem ki? A másik leggyakoribb probléma, egy nagyon idegesítő hiányosság, ami szintén az előző felületre való visszalépés hiányosságaiból alakul ki. Van egy listám, amin a találatokat tudom kereséssel, rendezéssel szűrni. Végül megtalálom azt a néhány dolgot, amit mondjuk szeretnék szerkeszteni. Rákattintok, és a felület átugrik a szerkesztő felületre. Elvégzem vele a dolgomat, és visszatérek az előző felületre, viszont meglepődve tapasztalom, hogy az nem úgy jön vissza ahogy otthagytam, hanem minden szűrés, keresés, rendezés elveszett, és írhatom be újra. Ez a példa azt mutatja, hogy a navigációhoz nem elég csak az a hívási láncot kezelni, hanem a felületek állapotának is meg kell maradnia, amikor az ember visszatér rájuk. Megfigyelhető, hogy ez egy alapvető intuitív elvárása minden felhasználónak. Ez persze automatikusan így van, ha a felületek állapotát az URL határozza meg, és az ember a böngésző vissza gombjával navigál. Akkor sem kell ezzel külön foglalkozni, ha ablakos rendszerben dolgozunk, hiszen ott egy adott felületet igazából el se hagyok, csak megnyílik felette az új.
Megvalósítani a felületek állapotának a megtartását, főleg egy általánosított formában, már komolyabb kihívás lehet. Ahogy a hívási láncot, az előző felületek adatait is tárolni kell valahol. Ehhez már egész biztosan kevés lesz az URL, egyszerűen azért mert korlátozott a hossza. Hidden input mezőkből ugyan megoldható, viszont ez is még mindig biztonsági rés lehet, mivel ugyanúgy manipulálható kliens oldalról. Legjobb megoldásnak marad tehát a session, személyes kedvencem. Akárhogy is, megvalósítását nagyon ajánlom mindenkinek, mert ez egy nagyon idegesítő és kényelmetlen hiányosság, és mint minden rossz felület, végül ahhoz vezet, hogy lassítja a felhasználó munkáját, ami pedig már komoly veszteség is lehet!
Most megint ki kell töltenem az egészet? Képzeljük el, hogy egy űrlapot töltünk ki, viszonylag sok adattal, és mikor végzünk vele, és rámentenénk, a rendszer közli velünk, hogy nem töltöttünk ki valamit helyesen. Semmi baj, rendes hogy szól, kitöltjük még azt is. Ám ebben a pillanatban meglátjuk, hogy az űrlap teljesen üres, és mindent elfelejtett amit előzőleg beírtunk. Amennyire
egyszerűen
megoldható
probléma
ez,
olyan
sokszor
lehet
látni
webes
felületeken, például amikor az ember be akar regisztrálni valahova. Tökéletes módszer a leendő felhasználók elriasztásához. Szóval tessék csak szépen visszaírni az űrlap mezőibe az előzőleg megadott adatokat, ennyi az egész, nem atomfizika, viszont rettenetesen rombolja a felhasználói élményt ha nincs megcsinálva.
Kérjük töltsön ki minden kötelező mezőt! Űrlapokon előfordulnak kötelező és nem kötelező mezők. A kötelezőket meg is szokás jelölni valahogy, és a rendszer természetesen ellenőrzi is, hogy ki vannak-e töltve, és szól ha nem töltöttük ki. Személy szerint, amikor ilyen felülettel találkozom, szeretem kipróbálni, hogy mi van ha szóközökkel töltöm ki a kötelező mezőket. Ezt ugyanis a legtöbb rendszer elfogadja, és úgy veszi, hogy kitöltöttem. Ez előfordulhat a felhasználó hibáján kívül tejlesen véletlenül is, és bár közvetlenül ugyan nem akadályozza a felhasználót semmiben, viszont rendszer üzemeltetőjének okozhat gondokat, és közvetetten a felhasználónak is, ha adatait nem adta meg megfelelően.
Programozók tehát figyeljenek arra, hogy szöveges mezőkben bevitt adatok elejéről és a végéről érdemes levágni a fölösleges szóközöket, és úgy vizsgálni, hogy üres-e. Szintén nem nagy tudomány, csak egy kis odafigyelés, viszont sokkal igényesebb.
Már tényleg csak 1 hiba van Űrlapok kitöltésénél minden tisztességes rendszer szól, ha valamit nem töltöttünk ki. Az viszont jó játék, amikor kapok egyetlen egy hibaüzenetet, hogy nem töltöttem ki valamit, és mikor már örülök, hogy csak azt az egy dolgot kell még megadnom és minden rendben, mentés után kapok még egyet. Aztán még egyet, és még egyet. Idegesítő, ha egy felület nem írja ki az összes hibát, hogy töltsem még ki ezt, azt és amazt, hanem itt a piros, hol a pirost játszik az emberrel. Tehát, tisztelt programozó társak, ne álljunk meg az első hibás adatnál, hanem szépen nézzük végig az összeset, és közöljük a felhasználóval mindet!
Biztonsági problémák Eltérve az eddig tárgyaltaktól, egy kicsit érdemes szót ejteni a felhasználói felületek megvalósításának biztonságtechnikai oldaláról. Magáról a webes biztonságról külön könyvet lehetni írni, de van néhány olyan tipikus probléma, ami a felületek kialakításával függ össze, és megkövetelheti, hogy bizonyos dolgokat technikailag máshogy valósítson meg a programozó. A web eredeténél fogva elég nyitott, és az egyik alapvető jellemzője az úgynevezett állapotmentesség. Ez azt jelenti, hogy amikor az ember egy weboldalon böngészget, akkor az a tény, hogy éppen hol van egy oldalon, nem tárolódik szerver oldalon, pusztán csak a böngészőben. Tehát mindig a böngésző mondja meg, hogy mit szeretne látni, és a szerver vakon teljesíti. Sokan pedig azt hiszik, hogy a felhasználó csak oda juthat el ahova mutat link. Ez nem igaz, bármikor beírhatok bármit az URL-be és akkor azt hívok be amit akarok. Akár olyan tartalmakat is, amit nem illene látnom.
User_id=1234 Korábban már említettük, hogy egy felület, vagy a weboldal állapotát nem célszerű az URLben tárolni, hacsak nem kifejezettem ez a célunk (pl.: hogy könnyen könyvjelzőzhető legyen az oldal). Vegyünk példának egy olyan esetet, ahol a felhasználó belép egy weboldalon a saját felhasználó nevével és jelszavával, és ott a saját ügyeit intézheti. Természetesen ahhoz a felülethez ahol ezt megteheti, csak bejelentkezés után férhet hozzá, és ott is csak a saját adatait láthatja és módosíthatja. Tegyük
fel,
hogy
egy
olyan
rendszerről
van
szó,
ahol
a
felhasználó
valamilyen
megrendeléseit intézheti. Lát egy listát a megrendelésekről, és a rákattint az egyikre, akkor megnyílik annak a részletes oldala. Azt, hogy melyik rendelés adait nézegeti a felhasználó éppen, sokszor, főleg tapasztalatlan programozók úgy oldják meg, hogy az URL-be tűntetik fel a rendelés azonosítóját, ez alapján fogja tudni a szerver, hogy mit kell megjeleníteni:
Igen, de mi történik ha én csak úgy átírom az 1234-et mondjuk 1235-re? Hopp, máris egy másik rendelés adatait látom, ami lehet, hogy nem is az enyém. Legrosszabb esetben még módosítani is tudom, vagy törölni, vagy ki tudja mit. Éppen ezért az URL alapján vezérelt felület rendszer nagyon sebezhető. Természetesen el lehet játszani vele, hogy szerver oldalon pluszba ellenőrzi a rendszer, hogy tényleg a saját rendelésemet akarom-e megnézni, és ha nem, akkor nem engedi megtekinteni. A gond csak az, hogy ezt a fajta ellenőrzést nem biztos hogy egyszerű általánosítani, és leginkább minden kritikus felületre meg kellene írni külön-külön, amit viszont a programozónak kell átgondolnia, hogy mik is az ilyen kritikus pontok. Márpedig a programozó is ember, és lehet hogy valamit kifelejt, vagy nem vesz észre, és ott mégis talál valaki támadási lehetőséget. Éppen ezért, ha biztosra akar menni az ember, akkor érdemes szerver oldalon tárolni (session) azt, hogy mikor milyen felület van nyitva, és épp mit nézeget a felhasználó. A problémát az se oldja meg, ha hidden input-okba tároljuk ezeket az információkat, mert azok is ugyanúgy manipulálhatóak. Természetesen
azok
a
felületek,
amik
eleve
publikusak,
és
szeretnénk
is
hogy
könyvjelzőzhetőek legyenek, működhetnek URL alapon, mint minden egyszerű weboldal.
Kérem ne nyomkodja az F5-öt! Szintén egy technikai hiányosság, ami problémákat okozhat, az ismételt lekérések (oldal frissítés). Ha pont egy műveletet végzett a felhasználó (például egy űrlap elküldése), és azután
ráfrissít
az
oldalra,
akkor
az
űrlap
újra
elküldődik.
Ez
azt
jelenti,
hogy
végrehajtódhat ugyanaz a művelet, pedig a felhasználó nem ezt szerette volna. A programozónak ezért figyelnie kell arra, hogy ugyanazt a kérést ne fogadja el többször a rendszer. Ezt meg lehet tenni azzal, hogy az űrlapokba valamilyen azonosító kódot helyezünk el, és szerver oldalon megjegyezzük ezeket az azonosítókat, és csak azokat a kéréseket fogadjuk el, amik a megfelelő azonosítókat tartalmazzák.
Tisztelt <script>!
HTML és Javascript injektálás, vagy más néven Cross Site Scripting (XSS). Ezek a fogalmak már elég mélyen benne van a webes biztonság témájában, de mégis itt tartom fontosnak megemlíteni, mivel a felületeket működtető rendszer lesz felelős a kivédéséért. A HTML és Javascript injektálás lényege az, hogy egy akármilyen űrlapon, ahol például a nevemet, címemet, stb kellene megadni, én javascript kódot írok be. Ha ezt, valahol a weboldal megjeleníti (eredetileg a nevemet írná ki), akkor bizony lefut a javascript kód, amivel mindenféle csúnyaságot el lehet követni.
Kivédése nem túl nehéz, egész egyszerűen az űrlapokról, és akár az URL-ből érkező adatokból is ki kell vágni a nem kívánatos HTML tag-eket, mint például a <script> tag. Erre a célra a webes programozási nyelvek adnak is beépített eszközöket, ezeknek mindenki nézzen utána az adott nyelven belül amivel dolgozik, és használja!