Accendo > Publikované > ASPX Úvod do ochrany – 04 SSO

Autor:                  Libor Bešenyi

Dátum:                2012/07/22

Zmena:                                2012/07/22

Single Sign-On

Dneska si povieme niečo o tom, ako dokáže dve nezávislé aplikácie prepojiť Form Authentication ticket. Je to veľmi jednoduché a nezväzuje to ruky, ak chcem používať špeciálne pravidlá v druhej aplikácii (iný role manager / user dáta sa sťahujú cez SOAP atď.).

Tento model mám (úspešne) použitý v živej prevádzke. Na začiatku bolo niekoľko aplikácií – starších / novších – dobre napísaných / zle napísaných. Každá požiadavka, ktorá sa javila natoľko nezávislá, aby sa dala naprogramovať ako oddelená aplikácia sa stala novým produktom. Užívateľ sa ale musel niekoľko krát prihlasovať, podľa toho, akú zónu chcel použiť.

Potom ale nastala aj požiadavka, aby sa začala deliť (ale aspoň nerozširovať) nosná aplikácia. Tu sme už ale potrebovali pevnejšiu previazanosť (užívateľ nemal čo vedieť, že keď klikne na ikonku tak „report“ mu vygeneruje iná aplikácia, lebo tá drží dáta). A zasa by bolo nevhodné, ak sa nachádzam v jednej zóne a kliknem na nejakú operáciu tak sa X-krát musí prihlásiť.

Potrebovali sme teda nejaký SSO model. A keďže väčšina systémov už používala Form Authentication (alebo jeho implementácia nebola až taká komplikovaná), voľba padla na SSO od Microsoftu. Autentifikácia sa teda bude vykonávať z hlavného uzla. Ak užívateľ zadá dopredu adresu na iný systém, ten ho redirektuje na Login page hlavnej aplikácie.

Celá predstava je pritom jednoduchá. Ako sme si povedali, o prihlásení serveru povie prehliadač. To, že o tom server nemusí vedieť (niesť informáciu niekde vo vlastnej pamäti), je výhodné, pretože takto vieme povedať, že sme prihlásený aj inému systému (aplikácii). Obmedzením ale je doména:

http://www.app1.domena.sk

http://www.app2.domena.sk

Sú kompatibilné. Toto už fungovať nebude:

http://www.app.domena-1.sk

http://www.app.domena-2.sk

Možno vám napadne aké to je s použitím SSL – ten samozrejme nehrá žiadnu rolu. App1 môže byť certifikovaný web, App2 nie atď.

Pridajme si teda do nášho testovacieho solution nový web. Obom webom priraďme port natvrdo. Nech pôvodná aplikácia má port 44444 a nová aplikácia 55555. Do App2 pridajme formulár WebForm1.aspx a spustime aplikáciu.

Sme na prihlasovacej obrazovke. Natvrdo napíšme Url na App2:

http://localhost:55555/WebForm1.aspx

App2 sa samozrejme zobrazí. Z minulých dielov vieme, že sme tam vlastne žiadnu ochranu nenakonfigurovali. Tak si teda otvorme web.config App2:

<authentication mode="Forms">

       <forms loginUrl="http://localhost:44444/WebFormLogin.aspx" />

</authentication>

 

<authorization>

       <deny users="?" />

</authorization>

 

Ako login stránku udajme App1 (tam už niet čo riešiť – všetko sme urobili v predchádzajúcich častiach). Ak chceme prepojiť dve nezávislé aplikácie, musia sa vedieť spárovať (kvôli identifikácii security ticketu). Obe aplikácie teda musia použiť rovnaký MachineKey. Na generovanie MachineKey sa dá použiť aj tento web:

http://www.orcsweb.com/articles/generate-aspnet-machine-key/

Kľúč, ktorý sa vygeneroval pridáme do OBOCH web.config súborov:

<machineKey validationKey='5172217443832F0CE3E60F2F40099BE0B471C67F746C71EB4C01C8EDC216E5582181876AEE5E179F3CFAA507F26C0EFBC201DC2C8B3B4E9D2EA0D2525D235499' decryptionKey='514F6AB7E84985F0C7F2F429463ECC1234CCB1773072C681' validation='SHA1' />

 

Ešte povolíme nejaké veci vo web.confug App1:

<forms loginUrl="~/WebFormLogin.aspx" defaultUrl="WebForm1.aspx" enableCrossAppRedirects="true" />

 

A máme to. V prípade živej compilácie je vhodné pridať aj Name (rovnaký na oboch stranách – kvôli cookies) a nutné je pridať Domain uzol – bez neho to na IIS6+ nerozchodíme! Takže si môžeme spustiť app. Z login obrazovky natvrdo zadáme Url na App2. Ako vidíme, App2 identifikovala, že užívateľ nebol prihlásený podobne, akoby sme pristupovali na App1. Akonáhle sa prihlásime tak App2 už bude prístupná.

Ak chcem zabezpečiť podobný spatný redirect po prihlásení (podobne ako ReturnUrl), musíme to odprogramovať. Vo Web.Config súbore App2 vieme pridať napr. url na Login obrazovku takto: .../WebFormLogin.aspx?ReturnApp=localhost:55555, pričom ReturnUrl sa tam pridá automaticky. Redirect po logine ale musíme ošetriť manuálne – pozrieť sa, či existuje parameter ReturnApp a kombinovať výsledné url s ReturnUrl parametrom. Žiadna veda (informácie ako na to máme z predchádzajúcich dielov).

Využitie Referrera môže byť problematické. Niektoré firewally strippnu http hlavičku a tak sa referrer nemusí medzi doménami predávať.

SlidingExpiration

Pri živej prevádzke by ste mali vedieť, ako fungujú expirácie ticketu (MSDN to popisuje). Ak máme zadefinovaný time-out na 20 minút, ale chceme, aby sa do úvahy brala aktivita užívateľa (nebol vykopnutý ak na webe pracuje), tak dá sa zapnú SlidingExpiration (parameter Autentifikácie vo web.configu).

Tento parameter od polky životnosti tiketu začne sledovať exspiráciu. Ak máme nastavený time-out na 20 minút, ale užívateľ bol aktívny len prvých 9 minút a v 21 minúte klikne niekde na stránke, bude odhlásený.

Ak však urobil aktivitu napr. v 11 minúte a potom až v 21, nič sa nestane, pretože sliding expirácia posunula 20 minútový interval od 11 minúty. Prečo to je rozdelené na polovice – viď rozsiahle diskusie na webe.

Timeouty nie sú všetko čo ovplyvňuje security ticket životnosť. Je tu ešte aj recyklácia poolu (condfigurácia IIS). Defaultne je nastavená na 20 minút. Tá má vplyv na aktivitu užívateľa tiež.

SQLServer Session

Použitie nie InProc session nastavení nie je problémom (sám ho používam). Bolo ale nutné ošetriť stavy ako je reštart aplikácie. Tým, že session je v podstate vždy živá, nastanú problémy s identifikáciu reštartu (upgradu) aplikácie. Ak sa potom začne deserializovať session, môžu nastať problémy, ak už interface novej verzie aplikácie nesedí s tým, čo je v session.

U nás sa to rýchlo poriešilo tým, že sa nasačkuje do session aj Guid, ktorý generuje aplikácia pri štarte (Global.asax). Tento Guid sa potom porovná pri Request evente (tiež Global.asax), ktorý je vlastne posielaný vždy – keďže browser hovorí serveru, že je všetko OK. Ak Session Guid nesedí s práve novo vygenerovaným App guidom, vieme, že aplikácia bola reštartovaná a takto môžeme vynúť (emulovať) session expired (alebo session clearnuť a naincializovať čo je potrebné ako pri prvom prihlásení).

Inicializácia session je vhodná aj pri logoute. Ten mohol zbehnúť z App1. Session key pre App2 môže byť v cookies a môže byť aktívny. Toto musíme tiež ošetriť, čo ak z jedného PC sa prihlasuje viacero ľudí (kaviareň). V App2 nesmieme nechať pôvodne dáta iného užívateľa a tak v session si môžeme pamätať aj čas prihlásenia (pri novej session vždy uložiť ten aktuálny). Ak časy nesedia, užívateľ sa medzi tým znova prihlásil a tak bude vhodné začať nové sedenie session. Zistenie času prihlásenie sa dá napr. takto:

((FormsIdentity)context.User.Identity).Ticket.IssueDate

Demo projekt: www.accendo.sk/download/AspxOchranaDemo04.zip