|
|
Bejelentkezési ablak készítése az internetes számlázóhoz
Internetes számlázó 3. rész
|
|
Példaprogram letöltése
31968 bájt
|
Következő lépés az internetes számlakészítő rendszerünk fejlesztésében a felhasználói bejelentkezések megvalósítása lesz. Meg kell oldanunk, hogy felhasználóink a web oldalon keresztül bejelentkezhessenek, valamint ellenőriznünk kell a UserData tábla alapján, hogy a bejelentkezést elfogadjuk, vagy elutasítjuk.
A mellékelt példa használatához a következő lépésekre van szükség:
- A Constanst.pas-ban módosítsa TEMPLATEPATH konstans-t úgy, hogy az a mellékelt template könyvtárra mutasson.
- Az IIS-ben az előző cikkben leírtak alapján létrehozott NetInvoice virtuális könyvtár elérési útvonalát módosítsa úgy, hogy az a mellékelt netinvoice könyvtárra mutasson.
- Web oldalon történő bejelentkezéshez használjuk a Rendszergazda bejelentkező nevet és az 123 jelszót.
Ha MS SQL adatbázist használunk, akkor módosítani kell a Constant.pas CONNECTIONSTRING, SQLUSERNAME és SQLPASSWORD konstansait is értelemszerűen.
Mostani részben tehát meg kell valósítanunk a bejelentkezés lehetőségét a web oldalunkon. Ezt a következőképpen tesszük meg: adott már a home.dat html állomány, melynek jobb felső sarkába beszúrjuk a login.dat html kódot tartalmazó állományt, amely megvalósítja a bejelentkezési lehetőséget. Ha a felhasználó már bejelentkezett, akkor a jobb felső sarokba a logged.dat állomány tartalmát szúrjuk be, mely jelzi a felhasználó számára, hogy a bejelentkezési azonosítás megtörtént. Ha a bejelentkezés közben hiba történik, akkor az error.dat kerül megjelenítésre, melyben közöljük a felhasználóval a hibaüzenetet.
Amikor a felhasználó megadta adatait, akkor kapcsolódnunk kell a userdata táblához, hogy ellenőrizhessük a megadott felhasználói név és jelszó érvényességét. Ha a bejelentkezés sikeres volt, akkor azt is meg kell valósítanunk, hogy az adott felhasználó a továbbiakban bármelyik web oldalunkat megtekinthesse újabb bejelentkezés nélkül, vagyis gondoskodni kell arról, hogy bejelentkezési információ egyik web oldalról átjusson a másikra.
Kezdjük:
A home.dat állományba beszúrunk egy <#login> sztringet, melyet a továbbiakban címkének nevezünk. Ezt a címkét arra a pontra helyezzük, ahova a login.dat, illetve a logged.dat állomány tartalmát szeretnénk beszúrni, attól függően, hogy a felhasználó bejelentkezett-e már vagy sem. Ha a html kódban <#egyedi név> formában helyezünk el címkét, akkor lehetőségünk van arra, hogy programból ezt a címkét egy tetszőleges html kódra lecseréljük egyszerűen. Az "egyedi név"-ként megadott sztring tetszőleges lehet, de figyeljünk arra, hogy egy állományon belül egyedi legyen. Ha többször használjuk ugyanazt az azonosítót, akkor az minden esetben ugyanarra a tartalomra lesz majd lecserélve. Persze lehet olyan eset, hogy pont erre van szükségünk.
A programban létrehozunk egy struktúrát, mely képes arra, hogy a userdata tábla egy rekordját tárolja. Így az alkalmazásunk futási ideje alatt csak egyszer kell majd lekérdezni az aktuális felhasználói adatokat és azokat utána már adatbázis kapcsolat nélkül is elérhetjük.
TUserData=record
UserID: integer;
UserName: string;
Password: string;
end;
Létre is hozunk ebből egy globális változót.
A felhasználói azonosítást úgy oldjuk meg, hogy minden linkbe elhelyezünk majd egy uid nevű paramétert, melynek értéke tartalmazza a felhasználói azonosítót kódolva.
Például: http://localhost/scripts/netinvoice.exe?uid=524187
Ehhez hasonlóan fogjuk megadni azt is, hogy aktuálisan milyen tevékenységet kell elvégeznie az alkalmazásunknak. Ehhez bevezetünk egy command paramétert, melynek értéke az elvégzendő műveletre utal.
Például: http://localhost/scripts/netinvoice.exe?uid=524187&command=2
E két paraméter bevezetésével a WebModule-ban értelmét veszíti a több akció létrehozása, így elegendő a már meglévő alapértelmezett akciót használni bármely jellegű kérés kiszolgálásához.
Nézzük, hogy miként módosul most az OnAction eseménykezelő.
procedure TWebModule1.WebModule1WebActionItem1Action(…);
begin
try
Induláskor meghívjuk a User belső eljárásunkat, mely értelmezi az uid paramétert.
Megpróbáljuk beolvasni a command paraméter értékét. Ha ez még nem létezne, akkor az alapértelmezett parancsot adjuk az FCommand változónak, melynek értéke nulla és amint ezt majd láthatjuk, a nyitó web oldalt fogja megjeleníteni.
try
FCommand:=StrToInt(Request.QueryFields.Values['command']);
except
FCommand:=0;
end;
Az FCommand globális változó feldolgozásához meghívjuk a Command belső eljárásunkat.
Tekintsük meg most a User eljárást, mely feldolgozza az uid paramétert. Ennek lényege az, hogy ha van megadva uid paraméter, akkor azt dekódoljuk és a userdata táblából előkeressük az adott felhasználó adatait és tároljuk a FUser globális változóban. Mivel e művelethez már szükséges adatbázis kapcsolat, így a következő előkészítő lépéseket tesszük:
Dbase adatbázis használata esetén hozzunk létre a BDE-ben egy NetInvoice nevű aliast, mely a cikksorozat első részében mellékelt DbaseData könyvtárra mutat.
MS SQL adatbázis használatához az ADO kapcsolat létrehozásakor szükségünk lesz a Constant.pas-ban megadott kapcsolódási sztring, felhasználói név és jelszó megadására.
- CONNECTIONSTRING='Data Source=as1\netsdk;User ID=sa;Password=;Provider=SQLOLEDB.1;Persist Security Info=False;Initial Catalog=NetInvoice;';
- SQLUSERNAME='sa';
- SQLPASSWORD='';
Mivel a rendszert úgy kell elkészítenünk, hogy egyaránt működjön Dbase és MS SQL adatbázissal is, így az egyszerűség kedvéért bevezetünk egy MSSQLVERSION direktívát és azt mondjuk, hogy ha ez adott, akkor MS SQL adatbázist kell használnia programunknak, míg ha ez nem létezik, akkor Dbase-t.
Ezek után jöhet a User eljárás.
procedure TWebModule1.User;
var
s: string;
uid: integer;
ds: TDataSet;
begin
Adott egy globális logikai típusú változónk, melyben azt jelezzük, hogy a felhasználó azonosítva lett-e már, vagy még ismeretlen.
FAnonymous:=true;
ds:=nil;
Lekérdezzük az uid paraméter értékét, melyet mindig sztringként kapunk meg.
s:=Request.QueryFields.Values['uid'];
Abban az esetben, ha az uid paraméter már meg van adva, akkor tudjuk csak a userdata táblából előkeresni az adatokat. Ellenkező esetben a felhasználó névtelen marad.
A kapott paramétert számmá konvertáljuk.
Ezt követően elvégezzük a szám dekódolását. Az uid paramétert kódolás nélkül nem igazán lenne célszerű megadni az URL-ben, hiszen ekkor bárki bejelentkezési név és jelszó nélkül hozzáférhetne a rendszerünkhöz. A példa egyszerűségének kedvéért most egy egyszerű kódolást használunk, mely nem nyújt nagy biztonságot, de cikksorozatunknak most nem is ez a feladata. A kódolás annyiból áll, hogy a felhasználó azonosító számát megszorozzuk egy a Constant.pas-ban elhelyezett konstans szám értékkel. Ezek után a dekódolást úgy végezhetjük el, hogy ugyanezzel a számmal visszaosztjuk a kapott uid paraméter értékét. Dekódolás előtt azonban ellenőrizzük, hogy a kapott szám valódi-e, vagyis maradék nélkül osztható-e a megadott számmal. Ha ez nem így lenne, akkor feltehetőleg a rendszerünk feltörésén fáradozik valaki és próbálgatja a kódokat. Ez esetben most nem teszünk semmit, csak meghagyjuk névtelen felhasználónak az illetőt.
if uid mod SECCODE=0 then begin
uid:=uid div SECCODE;
A következő lépésben el kell ágaztatnunk a programunkat, attól függően, hogy MS SQL, illetve Dbase adatbázist akarunk-e használni. A direktíva felhasználásával csak a megfelelő sor kerül be az EXE-be.
{$ifdef MSSQLVERSION}
ds:=tSQLUserData;
{$else}
ds:=tDbaseUserData;
{$endif}
Most már megnyithatjuk a megfelelő UserData táblát.
Ahol, ha sikeresen megtaláljuk felhasználót, akkor a névtelenséget jelző változót nyugodtan átállíthatjuk.
if ds.Locate('UserId', uid, []) then begin
FAnonymous:=false;
end;
end;
except
end;
end;
Végezetül, ha sikerült a felhasználót azonosítani, akkor már csak fel kell töltenünk az FUser változó TUserData struktúráját a felhasználói adatokkal későbbi felhasználás céljából.
if not FAnonymous then begin
with FUser do begin
UserID:=ds.Fields[0].AsInteger;
UserName:=ds.Fields[1].AsString;
Password:=ds.Fields[2].AsString;
end;
ds.Close;
end;
end;
A WebModule-unk alapértelmezett akciójában meghívott másik belső eljárás a Command, mely a command paraméter értéke alapján elvégzi a szükséges web oldal generálását és azt visszaküldi a kliensnek.
Ebben az eljárásban a programot egy case utasítással elágaztatjuk az FCommand globális változó értéke alapján. Ez tárolja az URL-ben megadott command paraméter értékét.
procedure TWebModule1.Command;
begin
case FCommand of
Ha a command paraméter nulla, akkor nem kell semmi különöset tennünk, csak megjeleníteni a home.dat-ban lévő nyitó web oldalt a már ismert módon.
0: begin
PageProducer1.HTMLFile:=TEMPLATEPATH+'home.dat';
Response.Content:=PageProducer1.Content;
end;
A command paraméter akkor kap 1 értéket, amikor a felhasználó a bejelentkezési ablak OK gombjára kattintva aktivizálja a programunkat. Ez a login.dat alábbi sora miatt történik meg:
<input type=hidden name=command value=1>
Ebben az esetben meghívjuk a Login nevű belső függvényünket, melynek paraméterként rögtön átadjuk a web oldalon megadott bejelentkezési nevet és jelszót. Ha a függvény igaz értékkel tér vissza, akkor a bejelentkezést elfogadtuk.
if Login(Request.QueryFields.Values['loginname'], Request.QueryFields.Values['password']) then
begin
Elfogadás esetén ismét a nyitó oldalra ugrunk, mely most már a logged.dat-ot jeleníti meg a bejelentkezési ablak helyén.
PageProducer1.HTMLFile:=TEMPLATEPATH+'home.dat';
Response.Content:=PageProducer1.Content;
end else begin
Ha a bejelentkezés nem lett elfogadva, akkor az error.dat kerül megjelenítésre, melyben tudatjuk a felhasználóval, hogy milyen hiba történt.
PageProducer1.HTMLFile:=TEMPLATEPATH+'error.dat';
Response.Content:=PageProducer1.Content;
end;
end;
end;
end;
Nézzük most, hogyan működik a Login függvény.
function TWebModule1.Login(username, password: string): boolean;
var
ds: TDataSet;
begin
Alapértelmezés szerint a bejelentkezést nem fogadjuk el, tehát hamis visszatérési értéket ad a függvényünk.
Ha a bejelentkezési név vagy a jelszó nem lett megadva, akkor máris hibajelzést küldünk a felhasználónak. A hibaüzenetet egy globális TStringList típusú változóban tároljuk, a felhasználására hamarosan visszatérünk.
if (username='') or (password='') then begin
FMessage.Add('Nem adta meg felhasználói nevét vagy jelszavát!');
end else begin
Ha van megadva adat, akkor eldöntjük, hogy melyik adatbázist használjuk annak ellenőrzéséhez.
{$ifdef MSSQLVERSION}
ds:=tSQLUserData;
{$else}
ds:=tDbaseUserData;
{$endif}
ds.Open;
Rákeresünk a felhasználói névre.
if ds.Locate('UserName', username, []) then begin
Ha a felhasználó megvan, akkor ellenőrizzük a jelszó helyességét.
if ds.FieldByName('password').AsString=password then begin
Ha a jelszó is stimmel, akkor a felhasználót azonosítottuk, ekkor létrehozzuk az uid paramétert és megadjuk a kódolt felhasználói azonosítószámot.
Request.QueryFields.Add('uid='+IntToStr(ds.FieldByName('userid').AsInteger*SECCODE));
Meghívva a User eljárásunkat, az uid paraméter alapján elvégezzük a felhasználói adatok tárolását.
A függvény visszatérési értékének igazra állításával jelezzük, hogy a bejelentkezést elfogadtuk.
result:=true;
end else begin
Ha a jelszó hibás, akkor ezt jelezzük a felhasználónak.
FMessage.Add('A megadott jelszó nem megfelelő!');
end;
end else begin
Ha nem találtuk meg a megadott felhasználót a userdata táblában, akkor ezt jelezzük a felhasználónak.
FMessage.Add(username+' nevű felhasználó nem található!');
end;
ds.Close;
end;
end;
A cikk elején már szó volt a <#login> címkéről, de még nem tárgyaltuk, hogy ezt miként cseréljük le a megfelelő tartalomra, vagyis a login.dat, illetve logged.dat állomány tartalmára.
A home.dat-ot, melyben szerepel a <#login> címke, a PageProducer1 komponens dolgozza fel. Van ennek egy OnHtmlTag nevű eseménye, mely minden olyan esetben létrejön a HTML kód feldolgozása során, amikor egy címke található a szövegben. Tehát amikor a PageProducer1 Content függvényét meghívjuk és az címkét talál a szövegben, akkor aktivizálja ezt az eseményt. Itt nyílik lehetőség arra, hogy a címkét egyedi tartalomra cseréljük.
procedure TWebModule1.PageProducer1HTMLTag(Sender: TObject; Tag: TTag; const TagString: String;
TagParams: TStrings; var ReplaceText: String);
begin
Az esemény TagString paraméterében kapjuk meg az aktuálisan megtalált címke nevét. Mivel egy állományban több címke is lehet, így ezt célszerű mindig ellenőriznünk.
if TagString='login' then begin
A login címke esetén ellenőriznünk kell, hogy a felhasználó azonosított-e vagy még névtelen.
Névtelen felhasználók számára olyan web oldalt kell generálnunk, melyben a login.dat állomány jelenik meg és így lehetőséget kapnak a bejelentkezésre. Hogy mire legyen a címke kicserélve, azt az eseménykezelő ReplaceText nevű paraméterében tudjuk megadni. A login.dat állomány beolvasásáról egy a PageProducer2 komponens gondoskodik.
PageProducer2.HTMLFile:=TEMPLATEPATH+'login.dat';
ReplaceText:=PageProducer2.Content;
end else begin
Ha a felhasználónk már azonosított, akkor a logged.dat állomány tartalmára cseréljük a login címkét.
PageProducer2.HTMLFile:=TEMPLATEPATH+'logged.dat';
ReplaceText:=PageProducer2.Content;
end;
end else begin
A hibaüzenetek megjelenítésére hoztuk létre az error.dat állományt. Ebben elhelyeztünk egy message címkét, melyet mindig az FMessage globális változóban tárolt üzenetekre kell cserélnünk. Ennek előállítására meghívjuk a belső GetMessage függvényünket.
if TagString='message' then begin
ReplaceText:=GetMessage;
end;
end;
end;
A GetMessage függvény működése egyszerű: egy ciklussal végigmegyünk a tárolt hibaüzeneteken és mindegyik szöveget valamint egy új sor HTML kódot helyezünk el a visszatérési értékbe.
function TWebModule1.GetMessage: string;
var
i: integer;
begin
result:='';
for i:=0 to FMessage.Count-1 do begin
result:=result+FMessage[i]+'<br>';
end;
end;
A logged.dat állományban olyan HTML kódot helyeztünk el, amely megjeleníti az aktuálisan bejelentkezett felhasználó nevét. Ezt úgy oldjuk meg, hogy a logged.dat-ban elhelyezünk egy loginname címkét. Amikor a PageProducer2 komponens feldolgozza a logged.dat-ot és megtalálja ezt a címkét, akkor kerül meghívásra az OnHTMLTag eseménye. Ez lesz az a pillanat, amikor kicseréljük a címkét az FUser-ben tárolt aktuálisan bejelentkezett felhasználói névre.
procedure TWebModule1.PageProducer2HTMLTag(Sender: TObject; Tag: TTag;
const TagString: String; TagParams: TStrings; var ReplaceText: String);
begin
if TagString='loginname' then begin
ReplaceText:=FUser.UserName;
end;
end;
A rendszerünk ettől kezdve már képes a felhasználók bejelentkeztetésére.
|
Könyv
Ez a cikk megtalálható ebben a könyvben:
Delphi Software Offline 2001 évkönyv 613. oldal
Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!
|