Delphi - ISAPI filter készítése 2. rész

Internet 18. rész

forráskód letöltése
Múlt héten egy olyan ISAPI filter DLL-t készítettünk, mely képes volt arra, hogy egy web szerverre (IIS, PWS) érkező összes kérésről eltárolja azt az információt, hogy a kérést küldő kliens, milyen típusú web böngészőt használ.

Ebben a cikkben azt vizsgáljuk meg, hogy miként készíthetünk olyan DLL-t, amelyik speciálisan csak azokat az információkat tárolja el egy-egy kérésről, hogy a webszerveren lévő melyik állományhoz próbált meg hozzáférni a kliens és ezt mikor próbálta megtenni, valamint azt, hogy milyen IP címről történt ez a kérés.

Mivel az adatokat tetszőleges formában tárolhatjuk, lehet akár egy adatbázis is, így az utólagos feldolgozáshoz könnyen készíthetünk saját alkalmazást. Az ISAPI filterről szükséges technikai tudnivalók a múlt héten ismertetésre kerültek, így ezeket itt nem ismételjük meg, viszont a cikk további részében feltételezzük az olvasóról, hogy az ott leírtakat ismeri.

A mostani programunk felépítése nagyban hasonló a múlt hetihez. Most viszont a GetFilterVersion függvényben már nem elegendő, ha a naplózási eseményt kérjük a szerver programtól.

Alábbiakban nézzük meg kissé részletesebben, hogy a GetFilterVersion függvénynél a THTTP_FILTER_VERSION típusú paraméter milyen értékeket tartalmazhat.
  • dwServerFilterVersion: DWORD; - ebből a mezőből az ISAPI szerver verziója tudható meg
  • dwFilterVersion: DWORD; - itt kell megadnunk a szerver számára a Filter DLL verzió számát
  • lpszFilterDesc: array[0..SF_MAX_FILTER_DESC_LEN - 1] of Char; - itt egy tetszőleges sztringet adhatunk, melyben röviden leírhatjuk, hogy mit is tesz a DLL-ünk.
  • dwFlags: DWORD; - ebben a paraméterben kerül megadásra, hogy milyen eseményekkor kérünk értesítést a szervertől. Ehhez az alábbi konstansokat használhatjuk fel:
    • SF_NOTIFY_READ_RAW_DATA: értesítést kapunk akkor, amikor a szerver adatokat olvas a kliens felől. Ez kérésenként akár többször is előfordulhat.
    • SF_NOTIFY_PREPROC_HEADERS: közvetlenül a kérés fejlécének előfeldolgozása után, de még a tartalom feldolgozása előtt.
    • SF_NOTIFY_URL_MAP: amikor a kérésből fizikai elérési útvonal generálódna, akkor értesítést kaphatunk, ha megadjuk ezt a konstanst. Ilyen lehet például egy http://www.animare.hu/dso/ kérés, és ebből a szerver a c:\Inetpub\wwwroot\dso\index.html-t rendelné hozzá, mint fizikai elérési útvonalat. Ebben az esetben az ISAPI filter-ben lehetőségünk van arra is, hogy ezt a fizikai útvonalat megváltoztassuk és a szerver a mi általunk adottat dolgozza fel.
    • SF_NOTIFY_AUTHENTICATION: mielőtt hitelesítené a klienst a szerver
    • SF_NOTIFY_ACCESS_DENIED: abban az esetben, ha a felhasználó olyan erőforrást szeretne elérni a szerveren, mely az ő számára nem engedélyezett, de még az előtt kapjuk az értesítést, hogy a szerver elküldené a hiba üzenetet a kliens felé. Ekkor lehetőségünk van módosítani ezt az üzenetet.
    • SF_NOTIFY_SEND_RESPONSE: a kliens kérésének feldolgozása végén, de még a fejléc elküldése előtt
    • SF_NOTIFY_SEND_RAW_DATA: adatküldés a kliens felé. Kérésenként többször is előfordulhat.
    • SF_NOTIFY_END_OF_REQUEST: a kliens kérés teljesítésének végén.
    • SF_NOTIFY_LOG: mikor a web szerver naplózza a kliens által küldött kérést.
    • SF_NOTIFY_END_OF_NET_SESSION: amikor a véget ér a klienssel a kapcsolat.

      Találunk még további konstansokat, melyek a DLL prioritását szabályozzák.
    • SF_NOTIFY_ORDER_DEFAULT: alapértelmezett
    • SF_NOTIFY_ORDER_LOW: alacsony szintű prioritás
    • SF_NOTIFY_ORDER_MEDIUM: közepes szintű prioritás
    • SF_NOTIFY_ORDER_HIGH: magas szintű prioritás

      Továbbá azt is szabályozhatjuk, hogy fenti események biztonságos kérés, vagy hagyományos kérés esetén is létrejöjjenek:
    • SF_NOTIFY_SECURE_PORT: eseményt kapunk, ha a kapcsolat a klienssel biztonságos port-on keresztül zajlik.
    • SF_NOTIFY_NONSECURE_PORT: eseményt kapunk, ha a kapcsolat a klienssel hagyományos port-on keresztül zajlik.

Fenti konstansok egymással kombinálhatók egyszerű összeadás művelettel és ezeknek az összértékét kell megadnunk a THTTP_FILTER_VERSION struktúra dwFlags mezőjének.


A HttpFilterProc függvényben most az SF_NOTIFY_URL_MAP üzenetet dolgozzuk fel. Itt a pfc változó GetServerVariable mezőjében tárolt eljárás segítségével lekérdezzük a szervertől az adott kliens IP címét.

A pvNotification változó az SF_NOTIFY_URL_MAP esetén egy PHTTP_FILTER_URL_MAP típusú struktúrára mutat. Ezen belül három változót találunk:

pszURL: ez a sztring tárolja a kérés URL-jét
pszPhysicalPath: ez a sztring tárolja a szerver által az URL-hez hozzárendelt fizikai útvonalat. Ha ezt módosítanánk, akkor megváltoztathatnánk az URL-hez tartozó web lap tartalmát.
cbPathBuff: az előbbi sztring maximum ilyen hosszú lehet.

Miután minden szükséges adatunk rendelkezésre áll most már nincs más teendő, mint kiírni azokat egy állományba. Mi most az egyszerűség kedvéért egy TXT állományba tesszük mindezt.

A programhoz mellékelt _filter2.txt-ben látható, hogy milyen eredményt szolgáltat a készített DLL.

Továbbá mellékeltünk egy Filter.reg nevű állományt is. Ennek segítségével egyszerűvé válik a Fillter DLL regisztrálása. Egyszerűen csak rá kell kattintani és nem kell a Windows regisztrációs adatbázisát kézzel módosítgatni, persze ha más DLL-hez használjuk, akkor nem árt előtte ezt az állományt módosítani és átírni benne a régi DLL nevét.

Internet cikksorozat