Hitelesítés + munkamenet kezelés megvalósítása PHP SOAP webszolgáltatásban
September 3rd, 2008
Ez az előző cikk folytatása konkrét példakódokkal.
Adatbázis
Tegyük fel, hogy az adatbázisban fogjuk tárolni a felhasználókat.
CREATE TABLE WsApiUsers (
ApiKey Char(32) NOT NULL UNIQUE,
SecretKey VARCHAR(40) NOT NULL UNIQUE,
PRIMARY KEY (ApiKey)
);
Az ApiKey egyedi azonosító a felhasználók azonosítására szolgál.
A SecretKey egy titkosító kulcs, ami nem összetévesztendő
a jelszóval. Ezzel a titkos kulccsal kell a felhasználónak titkosítania egy
sztringet (a sessionId-t), amit majd a kiszolgálótól kap.
Szükségünk van még egy adatbázis táblára, amelyben az
éppen aktív munkamenetek listáját fogjuk tárolni.
Minden munkamenetet az egyedi SessionID azonosít, és ehhez még különböző információk társulnak.
| SessionID | A munkamenet egyedi azonosítója. |
| IP | A kliens IP cime. Jól jöhet ez az információ, ha a későbbiekben úgy döntünk, hogy feljavitjuk az autentikációt. Például az autentikáció a jelszó és a felhasználói néven kívül ellenőrizné még a kliens IP címét is. Csak egy bizonyos IP címről, vagy IP cím subnetről érkező SOAP üzeneteket engedne tovább. Így valamelyest erősítenénk a webszolgáltatás biztonságát. |
| UserID | Ez egy idegen kulcs, és a WsApiUsers adatbázis táblára mutat. Ha értéke NULL, a kliens még nem jelentkezett be (nincsen autentikálva), kiléte ismeretlen. |
CREATE TABLE WsActiveSessions (
SessionID Char(40) NOT NULL UNIQUE,
IP Char(32) NOT NULL,
UserID SMALLINT UNSIGNED NULL,
Primary Key (SessionID),
FOREIGN KEY (UserID) REFERENCES WsApiUsers (ID)
)
ENGINE=HEAP
MAX_ROWS = 250;
A kliens
A kliensnek először egy munkamenet azonosítót kell kérnie a getSessionId tagfüggvény meghívásával.
Második lépésben összefűzzük a titkos kulcsot a kiszolgálótól kapott sessionId-val, majd a kapott
karakterláncból egy 128 bites kivonatot képezünk MD5 titkosítással. Ebben az a jó, hogy a titkos kulcsunkat nem
küldjük el a hálózaton keresztül.

Figyeljük meg az XML üzeneteket. Vegyük észre, hogy a login metódus meghívása már
tartalmazza a SOAP Header elemben a munkamenet azonosítót. A getSessionId metódus ugyanis
az egyetlen metódus, amely meghívható üres SOAP Header elemmel, a többi metódus
megköveteli a sessionId jelenlétét a SOAP fejlécben.
A kiszolgáló
Kezdjük a WSDL megírásával.
A munkamenet azonosítót így deklaráltuk a WSDL fájlban:
Arra van szükségünk, hogy hozzáférjünk a SOAP üzenet fejlécében lévő sessionId elem tartalmához.
Erre konkrét példát egy előző blogbejegyzésben találunk:
"PHP SOAP kiterjesztés - SOAP Header használata".
Továbbá azt is tudnunk kell, hogy a kliens melyik metódust hívta meg.
Ezt is az XML üzenetből tudjuk kiparszolni a köv. kóddal (a lényeg az XPath kifejezés).
Ha a kliens a getSessionId tagfüggvényt hívta meg, akkor nem ellenőrizzük a sessionId jelenlétét a SOAP fejlécben.
Ellenkező esetben SOAP fault-ot dobunk, ha a sessionId hiányzik a SOAP fejlécből.
Amikor megkaptuk a sessionId-t a SOAP üzenetben, leellenőrizzük, hogy létezik-e ilyen aktív munkamenet a
WsActiveSessions adatbázis táblában. Ha igen, akkor felújítjuk a PHP sessiont a
session_id() PHP funkcióval.
Ettől a pillanattól kezdve elérhetőek a klienshez tartozó session változók is.
PHP SOAP kiterjesztés - SOAP Header használata
September 3rd, 2008
Minden SOAP üzenet tartalmaz egy kiegészítő SOAP fejlécet (Header elem).
Az opcionális fejléc elem, a Header kiegészítő adatok megadására szolgál.
Ugyanabból a célból létezik, mint a HTTP Header. Leggyakrabban a Header elembe
a munkamenet (session) azonosítót, vagy a kliens hitelesítéséhez szükséges adatokat teszik.
Kliens
Lássuk, hogyan kell a PHP5-ben megjelent SOAP kiterjesztéssel beállítani egy SOAP fejlécet.
Tegyük fel, hogy a munkamenet azonosítot kell elküldenünk minden egyes SOAP üzenetben.
A Header elem bármilyen elemeket tartalmazhat, csakis tőlünk függ a tartalma
(na meg persze a kiszolgáló oldalon a WSDL fájlban deklaráltaktól).
A példa kedvéért a munkamenet azonosítót egy sessionId nevű elemben kell elhelyeznünk,
ami egy további ApiUserAuthHeader szülő elemben kell, hogy legyen. Ezek az elemek pedig a
urn:ExampleAPI névtérben kellenek, hogy legyenek.
Lássunk egy kész SOAP üzenetet, amit a kliens küld a kiszolgálónak.
Íme a PHP kód:
A SoapHeader osztály
szolgál SOAP fejléc létrehozására. Létre kellett hoznunk egy ApiUserAuthHeader osztályt, aminek egy
sessionId tulajdonságot adunk.
Annak ellenére, hogy a SoapHeader konstruktorában, az első paraméterrel beállítottuk az urn:ExampleAPI, a SOAP
kiterjesztés valamilyen okból mégsem ad a sessionId elemnek prefixet,
ezért volt szükség az ApiUserAuthHeader osztály konstruktorában a sessionId-t SoapVar objektummal létrehozni
(egyébként elég lett volna egy sima publikus sessionId nevű változó is).
Erről itt olvashatunk többet: http://bugs.php.net/bug.php?id=40318&edit=1.
A login metódusnak a paramétereket így is átadhattuk volna, ez is helyes megoldás:
Ha viszont így hívtuk volna meg a login metódust, akkor a SOAP kiterjesztés helytelenül kódolta volna a paramétereket a SOAP törzsben.
$ret = $client->__call('login',array('WorkaholicGroupApiKey','0c9ed93ec403851a2f7682aceb98a5a9'));
Kiszolgáló
Kiszolgáló oldalon a következőkre van szükségünk:
Elkapni a beérkezett SOAP XML üzenetet
$request = file_get_contents('php://input');
Kiparszolni belőle a sessionId elem tartalmát
Linkek
Eclipse - Web Service Explorer
June 21st, 2008
Az Eclipse fejlesztőkörnyezet hasznos eszközöket nyújt webszolgáltatások fejlesztőinek is.
Egyik ilyen hasznos eszköze (az Eclips-hez írt Web Tools Platform része) a
Web Service Explorer.
SOAP webszolgáltatások tesztelésére, debuggolására szolgál. Az Eclipse letöltési oldaláról az Eclipse Classic-ot ajánlom letölteni, mivel ahhoz már nem kell semmit sem hozzáinstallálni.

