Programmering

Sporing af sessionens udløb i browseren

Så der er den komplekse heterogene webapplikation med AJAX-dele udført både manuelt og ved hjælp af rammer, flere pop op-vinduer osv. En stor respektabel klient henvender sig til dig med et krav om at ugyldiggøre, lukke eller udføre en anden aktivitet på hele nettet applikationsvinduer, når HTTP-session udløber. Forhåbentlig ved du, hvordan du styrer HTTP-sessionens timeout-interval, for en J2EE-kompatibel webapplikation udføres det fra en web.xml-fil (men i mange app-servere gøres det ikke på en standard måde). I 10 minutters timeout er det:

  10  

Klientkravet er slet ikke absurd og giver perfekt mening ud fra slutbrugerperspektivet, men det kan blive en frygtelig smerte for en udvikler, fordi: 1. Du kan ikke bare starte en nedtællingstimer i browservinduet hver gang siden indlæses at lukke vinduet ved timeout. Denne tilgang fungerede i en ikke-AJAX-verden, når hver browser-server-interaktion resulterede i browservindue genindlæst. 2. Du kan ikke forespørge serveren for at kontrollere, om HTTP-sessionen er timeout eller ej, da hver sådan forespørgsel behandles som en browser-server-interaktion, der forlænger sessionen. Dette vil føre til en session, der aldrig udløber. 3. Du kan oprette en separat webapplikation, der er opmærksom på den primære webapps HTTP-session og krydser den. Men det er en overkill, og chancerne for, at en sådan løsning bliver accepteret, er ekstremt lave på grund af integrationsproblemer, der sandsynligvis vil opstå. 4. Du kan prøve at opfange alle AJAX browserserver-interaktioner med nogle avancerede hack-lignende kode, og det vil hjælpe dig med at håndtere dit nuværende vindue. Men dette fungerer ikke for tilfældet med flere åbne vinduer - du kan bare ikke kommunikere mellem browservinduer. Den eneste måde at tale med et åbent vindue fra et primært vindue er at bruge et andet vindues JavaScript-reference, og når det primære vindue genindlæses eller dirigeres til en anden placering, mister det alle JavaScript-referencer til andre vinduer. 5. Den mest realistiske tilgang er at foretage periodiske JavaScript-XMLHTTP-anmodninger (fra hvert åbent vindue) til serveren hver {session maks. Inaktivt interval} +10 sekunder. Dette lukker i sidste ende alle vinduer, men kan resultere i, at vinduer lukkes minutter (eller endda timer afhængigt af web-app-sessionens timeout-indstilling), efter at HTTP-sessionen bliver ødelagt, f.eks. når brugeren logger ud fra det primære vindue. Der er ikke flere muligheder tilbage, du er frustreret, og du tror, ​​at det er det rigtige tidspunkt at tage din fars pistol og skyde dine klassekammerater på skolen i morgen. Nej, endnu ikke barn - der er stadig en vej ud! Vejen ud er ikke meget ligetil, men er meget elegant. Cookies hjælper os. Man kunne tro, at udløbstid for cookies ville gøre tricket. Desværre, som beskrevet i

det her

artikel, kan du ikke stole på udløbstid for cookie, da den måles af en klientbrowser, og ingen kan garantere, at klientsystemets ur ikke er et år bagud. Så her er systemet og metoden til sporing af HTTP-sessionstime-outs i heterogene webapplikationer. På hver anmodning fra en browser til en server indstilles to cookies af et servletfilter. Den ene holder serverens aktuelle tid, og en anden holder sessionens udløbstid. Serverens aktuelle tid er kun nødvendig for at beregne en forskydning mellem klient og server. Sessionens udløbstid kontrolleres derefter med jævne mellemrum mod den _beregnede_ aktuelle servertid (husk forskydningen). Hver gang _anlig_ anmodning sendes til serveren, opdateres cookie til udløbstid, og det hele fungerer bare. I praksis realiseres denne metode i kun tre trin: 1. Opret et servletfilter, der filtrerer hver eneste anmodning til din webapplikation. Konfigurer det i web.xml sådan:

  SessionTimeoutCookieFilter noget.pakke.SessionTimeoutCookieFilter SessionTimeoutCookieFilter / * 

Du skal ikke bekymre dig om din webapps ydeevne - dette filter er MEGET primitivt, alt det gør er at tilføje to cookies til svaret:

 public void doFilter (ServletRequest req, ServletResponse resp, FilterChain filterChain) kaster IOException, ServletException {HttpServletResponse httpResp = (HttpServletResponse) resp. HttpServletRequest httpReq = (HttpServletRequest) req; lang currTime = System.currentTimeMillis (); lang udløbstid = currTime + session.getMaxInactiveInterval () * 1000; Cookie cookie = ny cookie ("serverTime", "" + currTime); cookie.setPath ("/"); httpResp.addCookie (cookie); hvis (httpReq.getRemoteUser ()! = null) {cookie = ny cookie ("sessionExpiry", "" + expiryTime); } andet {cookie = ny cookie ("sessionExpiry", "" + currTime); } cookie.setPath ("/"); httpResponse.addCookie (cookie); filterChain.doFilter (req, resp); } 

Indstilling af sti (til "/" i vores tilfælde) er meget vigtig. Hvis du udelader stiindstilling, beregner browseren den automatisk ud fra URL'en, hvilket vil resultere i kaos i din browsers cookies-opbevaring. 2. Vi har brug for et lille JavaScript i hvert vindue for at beregne forskydning mellem server og klienttid. Det skal køres kun én gang, men det ville ikke skade at køre det på hver sideindlæsning:

 funktion calcOffset () {var serverTime = getCookie ('serverTime'); serverTime = serverTime == null? null: Math.abs (serverTime); var clientTimeOffset = (ny dato ()). getTime () - serverTime; setCookie ('clientTimeOffset', clientTimeOffset); } window.onLoad = funktion () {calcOffset (); }; 

3. Og til sidst har vi brug for en funktion, der faktisk kontrollerer, om sessionen er timeout. Det skal udføres periodisk, i vores tilfælde hvert 10. sekund (eller 10000 millisekunder):

 function checkSession () {var sessionExpiry = Math.abs (getCookie ('sessionExpiry')); var timeOffset = Math.abs (getCookie ('clientTimeOffset')); var localTime = (ny dato ()). getTime (); hvis (localTime - timeOffset> (sessionExpiry + 15000)) {// 15 ekstra sekunder for at sikre, at window.close (); } ellers {setTimeout ('checkSession ()', 10000); }} 

Faktisk er lukning af browservinduer efter sessionens udløb ren brutalitet, og det kan og bør ledsages af en advarselsmeddelelse, der dukker op som 1 minut før sessionens timeout. Jeg er virkelig interesseret i at modtage din

kritisk feedback

på min metode.

Denne historie, "Tracking session expiration in browser" blev oprindeligt udgivet af JavaWorld.