Contexte :
Tomcat permet de d’intercepter les requêtes et les réponses. Cela peut s’avérer intéressant pour faire différents traitements tel que par exemple l’encodage des paramètres d’une requête (encodage systématique), la gestion propre d’un logout avec invalidation de la session… Les applications sont multiples.
Les Valves Tomcat :
La technologie des Valves est propre à Tomcat et n’existe pas forcement sur les autres serveurs d’application (En tout cas pas sous cette forme).
La Valve, lorsqu’elle est appelée, intercepte la requête Http avec et met a disposition les paramètres Request et Response de celle-ci. Elle étend la classe « org.apache.catalina.valves.ValveBase » et doit surcharger la méthode « invoke ».
On peut créer autant de Valves que l’on veut et celles-ci vont s’enchaîner lorsqu’on appelle la méthode « getNext().invoke ». Si cet appel est homis, aucune autre valve sera appelée.
Les Valves sont invoquées dans l’ordre de leurs déclaration dans le fichier Xml.
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Invalidation des sessions */ public class LogoutValve extends ValveBase { private static final Logger LOGGER = LoggerFactory.getLogger(LogoutValve.class); @Override public void invoke(Request pRequest, Response pResponse) throws IOException, ServletException { if (pRequest.getParameterMap().size() > 0 && pRequest.getParameterMap().containsKey("amp;portal:action") && ((String[]) pRequest.getParameterMap().get("amp;portal:action"))[0].equals("Logout")) { // On invalide la session et on crée une nouvelle session LOGGER.info("Logout : Invlidation de la session !"); pRequest.getSession(true).invalidate(); pRequest.setRequestedSessionId(null); pRequest.clearCookies(); // Create a new session and set it to the request Session newSession = pRequest.getSessionInternal(true); pRequest.setRequestedSessionId(newSession.getId()); // Redirection vers l'accueil ((HttpServletResponse) pResponse).sendRedirect(pRequest.getRequestURL().toString()); } else { // Passage a la prochaine valve super.getNext().invoke(pRequest, pResponse); } } } }
Paramétrage des Valves dans le portal.xml :
<Context path="/portal" docBase="portal" debug="0" reloadable="true" crossContext="true" privileged="true"> <Valve className='org.toto.filtre.LogoutValve' characterEncoding='UTF-8' /> </context>
Javax.servlet.Filter
Les filtres du package « Javax » permettent un fonctionnement similaire. Lorsqu’on les paramètre dans le « web.xml » on leurs indique un « url-pattern » qui va définir sur quelle url le Filtre doit se déclencher. Du coup on peut, par rapport aux Valves, affiner leurs déclenchement et ne pas le rendre systématique.
Les filtres s’enchaînent aussi et on laisse la possibilité au développeur de continuer le chaînage des filtres ou d’intérompre celle-ci. Le 3e paramètre, FilterChain, permet donc de gérer la pile d’appel des filtres.
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class LogoutFilter implements Filter { @Override public void doFilter(ServletRequest pRequest, ServletResponse pResponse, FilterChain pFilterChain) throws IOException, ServletException { // On invalide la session et on crée une nouvelle session ((HttpServletRequest) pRequest).getSession().invalidate(); ((HttpServletRequest) pRequest).getSession(true); } }
Paramétrage des filtres dans le web.xml :
<filter> <filter-name>logoutFilter</filter-name> <filter-class>org.toto.web.LogoutFilter</filter-class> </filter> <filter-mapping> <filter-name>logoutFilter</filter-name> <url-pattern>/logout</url-pattern> </filter-mapping>