# Sessionmanagement und Tomcat



## RichardWimmer (7. Jun 2011)

Hallo an alle,

ich habe ein kleines Problem beim Sessionmanagement mit Tomcat das ich nicht verstehe. Ich habe eine Applikation mit Java Server Pages und Servlets geschrieben. Am Anfang muß sich der benutzer anmelden, eine Session wird initiert. Am Anfang jeder jsp und jedes Servlets frage ich die Gültigkeit der Session ab um zu verhindern, dass das Programm einen Stacktrace ausgibt wenn die Session abgelaufen ist. 
Das funktioniert auch in 99% wunderbar, ich habe jedoch immer wieder Clients, die mittendrin die Session verlieren und dann immer wieder auf die Anmeldeseite zurück kommen.

Hier mein Code:

Dieses Servlet wird vom Login Screen aufgerufen. Am Anfang initiiere ich eine neue Session


```
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,	IOException

	{
		RequestDispatcher rd = null;
		// Alte Session löschen
		try
		{
			request.getSession(false).invalidate();
			request.getSession(true);
		} catch (RuntimeException e)
		{
			rd = this.getServletContext().getRequestDispatcher("/b/noCoockie.html"); //$NON-NLS-1$ //$NON-NLS-2$
			rd.forward(request, response);
			return;
		}
		System.out.println("ID: " + request.getSession(false).getId());
		
		//Weiterer Code zur Validierung des Login
	}
```
 

Jede jsp Seite enthält am Anfang diesen Teil


```
<head>
<jsp:include page="../layout/sessionexpired.jsp" />
```


Dies ist dann die Datei sessionexpired.jsp

```
<%
	if (!request.isRequestedSessionIdValid())
	{
		out.println("<meta http-equiv='refresh' content='0; URL=/ipk/sessionexpired.html'>");
		out.flush();

	}
%>
```


Bei Servlets sieht es so aus


```
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
	// Gültigkeit der Session abfragen und ggf. auf die Anmeldeseite zurück
	RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/sessionexpired.html");
	if (!request.isRequestedSessionIdValid())
	{
		rd.forward(request, response);
		return;
	}
```

Wer hat eine Idee was ich hier falsch mache. Wie gesagt, der Fehler tritt nur sporadisch und nicht nachvollziehbar auf. Mit dem betroffenen Client hat man dann auch keine Chance mehr weiterzuarbeiten. Er wird immer wieder auf die Loginseite zurück geleitet. Provozieren kann ich das Verhalten in dem ich am Client das Session Cookie lösche.

Vielen Dank

Richard Wimmer


----------



## brauner1990 (8. Jun 2011)

Du solltest kontrollieren wie hoch deine TTL der Sessions ist, und die User mal fragen, ob diese länger inaktiv waren.


----------



## RichardWimmer (8. Jun 2011)

Danke für Die Antwort. Das kann es aber nicht sein. Das Sessiontimeout setzte ich weiter unten im Servlet.

```
if (benutzer.getKn_rechte() > 0)
{
	// Sessiontimeout für interne Benutzer auf 2 Stunde setzen
	request.getSession().setMaxInactiveInterval(7200);
} else
{
	// Sessiontimeout für externe Benutzer auf 1/2 Stunde setzen
	request.getSession().setMaxInactiveInterval(1800);
}
```

Es ist auch nicht so, dass der Anwender einmal rausgeschmissen wird und nach einem erneuten Einloggen sofort wieder weiter arbeiten kann. Er wird dann immer wieder unmittelbar bei der nächsten Prüfung der Gültigkeit der Session rausgeschmissen.


----------



## maki (8. Jun 2011)

```
<%
    if (!request.isRequestedSessionIdValid())
    {
        out.println("<meta http-equiv='refresh' content='0; URL=/ipk/sessionexpired.html'>");
        out.flush();
 
    }
%>
```
Das wird imho nciht zuverlässig funktionieren, wenn schon content gesendet wurde wie zB. beim templating, wird der neue Header ignoriert im besten Falle, im schlechtesten Falle gibt es einen Fehler.
Sowas macht man doch normalerweise mit einem Filter, Beispiele gibt es genug im Netz wenn man nach "Session Filter" etc. sucht.


----------



## RichardWimmer (16. Jun 2011)

Vielen Dank für den tollen Tip. Hat eine Zeit gedauert, bis ich das mit den Filtern kappiert habe, jetzt läuft es aber wunderbar. Habe aber noch einige Fragen. Kommt mein Fehler nur aus der Sessionprüfung in den jsp dateien oder sollte ich die Sessionprüfung im Servlet besser auch auf die Filter umstellen. Habe meinen Filter jetzt wie folgt implemetiert:

```
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
			ServletException
	{
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		String url = request.getServletPath();
		System.out.println("url: " + url);
		boolean allowedRequest = false;
		if (urlList.contains(url))
		{
			allowedRequest = true;
		}
		
		String fileType = url.substring(url.indexOf(".")+1);
		//System.out.println("fileType: " + fileType);
		if (typeList.contains(fileType))
		{
			allowedRequest = true;
		}

		
		if (!allowedRequest)
		{
			System.out.println("Check Session");
			HttpSession session = request.getSession(false);
			if (null == session)
			{
				//System.out.println("Session expired");
				response.sendRedirect("/ipk/sessionexpired.html");
			}
		}
		chain.doFilter(req, res);
	}

	public void init(FilterConfig config) throws ServletException
	{
		String urls = config.getInitParameter("avoid-urls");
		StringTokenizer token = new StringTokenizer(urls, ",");
		urlList = new ArrayList<String>();
		while (token.hasMoreTokens())
		{
			urlList.add(token.nextToken());
		}
		String types = config.getInitParameter("avoid-types");
		token = new StringTokenizer(types, ",");
		typeList = new ArrayList<String>();
		while (token.hasMoreTokens())
		{
			typeList.add(token.nextToken());
		}
		/*for (String s : typeList)
		{
			System.out.println(s);
		}*/
	}
```
Immer wenn der Fall Session expired eintritt wir der Benutzer auch auf die Seite sessionexpired.html umgeleitet. In der Console bekomme ich dann aber folgende Fehlermeldung:

```
url: /b/start-d.jsp
Check Session
16.06.2011 11:19:54 org.apache.jasper.runtime.JspFactoryImpl internalGetPageContext
SCHWERWIEGEND: Exception initializing page context
java.lang.IllegalStateException: Cannot create a session after the response has been committed
	at org.apache.catalina.connector.Request.doGetSession(Request.java:2221)
```
Wo kommt das her?


----------



## maki (16. Jun 2011)

Nun ja, er kann keine neue Session erzeugen wenn der Respone schon committed wurde, steht zumindest so in der Fehlermeldung 

Macht aber Sinn, die Session muss entweder als Cookie oder  URL Encoded zum Client gesendet werden, das geht halt nicht mehr wenn der Client die Seite schon ausgeliefert bekommen hat.

Du musst imho schon vorher eine neue Session erzeugen.

Sessions werden übrigens immer vom ServletContainer an Clients vergeben, auch bevor sie sich authentifiziert/autorisiert haben, irgendwie muss der Server den Client ja erkennen können


----------



## RichardWimmer (16. Jun 2011)

Vielen Dank für die Hilfe, jetzt hab ich's kappiert (hoffentlich)


----------

