jsf - example - java session management
JsessionId-cómo evitar; jsessionid=XXX en la primera llamada a una página? funciona si la primera página es jsp (3)
Bueno, ya terminé con esto ...
Tengo una aplicación que usa la página de bienvenida index.jsp con un <iframe></iframe>
el contenido del iframe es una página jsf. Si tengo acceso a index.jsp, ya veo una cookie en el primer enlace de Firebug:
Set-Cookie JSESSIONID=C615DA89B6EF73F801973EA3DCD3B226; Path=/
La página del <iframe>
hereda este jsessionid. PERO: cuando accedo directamente a la página del <iframe/>
consigo el jsessionId reescrito en todas las URL sin una cookie, en la primera solicitud. Luego se usa la cookie. Todo está bien, si: el sistema de seguridad me permitiría realizar reescrituras de URL.
Ejecuto jboss 4.2.2
Quiero lograr el mismo comportamiento que tengo con index.jsp, por ejemplo, siempre usar cookies y siempre evitar la reescritura http.
[EDITAR] gracias a la respuesta de balusc escribí esto:
public class JsessionIdAvoiderFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
boolean allowFilterChain = redirectToAvoidJsessionId((HttpServletRequest) req, (HttpServletResponse)res);
//I''m doing this because if I execute the request completely, it will perform a pretty heavy lookup operation. No need to do it twice.
if(allowFilterChain)
chain.doFilter(req, res);
}
public static boolean redirectToAvoidJsessionId(HttpServletRequest req, HttpServletResponse res) {
HttpSession s = req.getSession();
if(s.isNew()) {
//after the redirect we don''t want to redirect again.
if(!(req.isRequestedSessionIdFromCookie()&&req.isRequestedSessionIdFromURL()))
{
//yeah we have request parameters actually on that request.
String qs = req.getQueryString();
String requestURI = req.getRequestURI();
try {
res.sendRedirect(requestURI+"?"+qs);
return false;
} catch (IOException e) {
logger.error("Error sending redirect. " + e.getMessage());
}
}
}
return true;
}
}
No olvides agregarlo a tu web.xml
<filter>
<display-name>JsessionId Filter</display-name>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<filter-class>my.namespace.JsessionIdAvoiderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
De acuerdo con la recomendación de Christopher Schultz, probé esto y funciona.
package com.rama.test.jsessionfilter
public class JsessionIdAvoiderFilter implements Filter {
protected static final Logger LOGGER = LogManager.getLogger(JsessionIdAvoiderFilter.class);
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
if (!(req instanceof HttpServletRequest)) {
chain.doFilter(req, res);
return;
}
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// Redirect requests with JSESSIONID in URL to clean old links
/* If you really want clean up some old links which have Jsession id bookmarked clean it. If its new app
this below check is not required. */
if (request.isRequestedSessionIdFromURL()) {
String url = request.getRequestURL().append(request.getQueryString() != null ? "?"
+ request.getQueryString() : "").toString();
response.setHeader("Location", url);
response.sendError(HttpServletResponse.SC_MOVED_PERMANENTLY);
LOGGER.info(" Found url with jsession id in it:"+ request.getRequestURL() +": url="+url);
return;
}
// Prevent rendering of JSESSIONID in URLs for all outgoing links
HttpServletResponseWrapper wrappedResponse = new HttpServletResponseWrapper(
response) {
@Override
public String encodeRedirectUrl(String url) {
return url;
}
@Override
public String encodeRedirectURL(String url) {
return url;
}
@Override
public String encodeUrl(String url) {
return url;
}
@Override
public String encodeURL(String url) {
return url;
}
};
chain.doFilter(req, wrappedResponse);
}
public void destroy() {
}
public void init(FilterConfig arg0) throws ServletException {
}
}
y la siguiente entrada en web.xml
<filter>
<display-name>JsessionId Filter</display-name>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<filter-class>com.rama.test.jsessionfilter.JsessionIdAvoiderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jsessionIdAvoiderFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Funciona genial !!!.
Desde Servlet 3.0 puede usar <tracking-mode>COOKIE</tracking-mode>
para esto. Pero como JBoss 4.2.2 no es un compilador de Servlet 3.0, esta no es una opción.
Lo más fácil sería crear un filtro de servlet que envíe un redireccionamiento a HttpServletRequest#getRequestURI()
cuando HttpSession#isNew()
devuelva true
. No olvide comprobar HttpServletRequest#isRequestedSessionIdFromCookie()
para evitar un bucle de redirección infinito cuando el cliente no admita cookies en absoluto.
Esto se puede hacer con un filtro simple que envuelve la solicitud con un HttpServletRequest que anula HttpServletRequest.encodeURL y HttpServletRequest.encodeRedirectURL. Simplemente devuelva el argumento String que se le haya pasado e inhabilitará la reescritura de URL. Tenga en cuenta que esto solo funcionará para una sola aplicación web a menos que desee configurarla en conf/web.xml
(no recomendado) o configurarla en todas sus aplicaciones web distintas.
Esta técnica es superior a la que se publicó más adelante en su pregunta porque no requiere redirección, lo que puede ralentizar sus solicitudes. OMI, también es más limpio.