Itt jársz most: Kezdőlap > Alkalmazásfejlesztés > Egyperces - Kényszerített session invalidálás

Szűrő megjelenítése

Egyperces - Kényszerített session invalidálás

Újabban elég sokszor hozom fel a készülő Leaflet nevű blogrendszeremet, ennek oka pedig annak továbbra is aktív fejlesztési stádiuma. A backend rendszer első főverziója már képes forgalom kiszolgálására, így a fejlesztések most az adminisztrációs rendszert érintik elsősorban. A Leaflet REST API-t biztosít kliens alkalmazásai (így az LMS nevű admin rendszer felé is), az authentikálást pedig így JWT tokenek biztosítják. Ezen tokenek saját lejárati időponttal rendelkeznek, továbbá a korábbi cikkemben említett session store lehetővé teszi azok követését és idő előtti invalidálását, ha a rendszer problémát észlel egy adott tokennel (bővebben a “JWT alapú authentikálás I - Tokenek követése” című cikkemben).

Mindeközben a kliens alkalmazások tetszőleges módon kezelhetik ezeket a tokeneket. A lényegen igazából nem változtat: a jogosultságok ellenőrzését minden esetben a Leaflet végzi. Ennek megfelelően, amennyiben egy token érvénytelenné válik, a kliens alkalmazás számára a további kommunikáció lehetetlen lesz. Az LMS jelenlegi megvalósítása alapján standard session-t hoz létre, a Leaflet által kiállított tokent pedig eltárolja abban. A kérések a továbbiakban ezen eltárolt token segítségével kerülnek authentikálásra. Így létrejön gyakorlatilag két egymástól lényegében független authentikálás: egy session és egy token alapú). Mivel a token alapú a “domináns”, a kliens alkalmazásban létrejött session élettartama teljesen tőle függ. És ezzel el is értünk a probléma gyökeréhez.

Hadd demonstráljam. Tegyük fel, a tokenek négy órán át érvényesek. Bejelentkezéskor létrejön a session a kliens alkalmazás oldalán, mely mondjuk hat óráig “életben lesz”. Miután letelik a négy óra, a token érvénytelenné válik, azonban az alkalmazás session-je alapján még van két óránk a munkafolyamat végéig, tehát az alkalmazás tovább próbálkozik kérések küldésével - az immáron lejárt tokennel. Természetesen a backend alkalmazás ezt nem fogja engedni és HTTP 401 válasszal díjazza majd a kliens próbálkozásait. Ez kliens oldalon kivételt vált ki és ha csak nem szüntetjük meg manuálisan a session-t, akkor ez a helyzet nem is fog változni a hátralevő két órában.

Itt jön a képbe a címben említett “kényszerített session invalidálás”, mely gyakorlatilag manuális kijelentkeztetésnek felel meg. Elég lehetne akár rákattintani a kijelentkezésre, de ez aligha elegáns, és kényszeríteni kell a felhasználót egy számára fölöslegesnek érződő lépés megtételére. Ráadásul kijelentkeznél érvényteleníteni kell a tokent, melyet már hiába küldenénk a backendnek, hiszen az már régen érvénytelen.

A problémát végül egy filterrel oldottam meg. A “trükk” mindössze annyi, hogy az invalidálási logikát a doFilter() hívás után kell elhelyezni, így a kérés ekkor már fel van dolgozva, a backend visszaküldte a válaszát, sőt a kiváltott kivétel miatt a megfelelő (HTTP 401) státusz is be van állítva. Az aktív session és a 401-es státusz együtt pedig egyértelműen árulkodó jelnek felelnek meg, ekkor lefuthat a filter logikája, mely három lépésből áll:

  • a felhasználó SecurityContext-jének kiürítése az aktuális threaden
  • a felhasználói session invalidálása, nyilvánvalóan annak érdekében, hogy megszűnjön az alkalmazás session-je, így elvesztve az érvénytelen tokent
  • a session cookie érvénytelenítése, hogy a kliens ne próbálja küldeni az ekkor már érvénytelenített sessionhöz tartozó cookie-t a szervernek
protected void doFilterInternal(HttpServletRequest request,
			HttpServletResponse response, FilterChain filterChain)
		throws ServletException, IOException {

	filterChain.doFilter(request, response);

	if (isAuthenticated() && isRequestUnauthorized(response)) {
		forceInvalidateUserSession(request);
	}
}
private void forceInvalidateUserSession(HttpServletRequest request) {

	SecurityContextHolder.clearContext();
	request.getSession(false).invalidate();
	Stream.of(request.getCookies())
			.forEach(cookie -> cookie.setMaxAge(0));
}

Ezen három lépés eredményeképp a felhasználó még látni fogja a hibaoldalt, mely szerint lejárt a session-je és jelentkezzen be, ezután pedig ha a felhasználó visszatér az alkalmazás főoldalára vagy bármely más útvonalát próbálja elérni, a bejelentkező oldalon köt ki.

Természetesen a felhasználó meglehetősen morcossá válhat, ha így legrosszabb esetben elvész a mentetlen munkája. Ennek megelőzésére került az alkalmazásba a session meghosszabbítás lehetősége, melyről a “JWT alapú authentikálás” című cikksorozatom következő részében írok majd.

Kommentek

Komment írásához jelentkezz be
Bejelentkezés

Még senki nem szólt hozzá ehhez a bejegyzéshez.