2010-12-27 12 views
6

Estoy escribiendo un filtro OpenID basado en la biblioteca JOID para permitir que las aplicaciones se autentiquen de forma transparente contra nuestro servidor OpenID local. Dado que OpenID funciona a través de redireccionamientos HTTP, termino perdiendo el objeto de solicitud original en el proceso, especialmente si se trata de un POST con un cuerpo de datos. ¿Es posible guardar el objeto de solicitud de manera que pueda reutilizarlo más adelante en la transacción, después de que el usuario haya sido autenticado? Incluso el solo hecho de guardar el cuerpo del mensaje en sí mismo debería ser suficiente, ya que puedo preservar la URL de la consulta con suficiente facilidad con un redireccionamiento de ida y vuelta (usando el retorno a la URL de OpenID).¿Guardar y reutilizar una solicitud en un filtro de servlet?

Quiero que esto sea completamente transparente para los servlets subyacentes, por lo que se comportan igual si el usuario pasó por el flujo de OpenID para esta solicitud en particular o simplemente tiene una sesión local válida/autenticada.

Respuesta

6

Almacene los datos de interés (parámetros de solicitud, atributos de solicitud, etc.) en un alcance de sesión Map mediante una identificación única como clave que agrega al retorno a la URL.

String id = UUID.randomUUID().toString(); 
DataOfInterest data = new DataOfInterest(request); 
Map<String, DataOfInterest> map = (Map<String, DataOfInterest) session.getAttribute("dataOfInterest"); 
map.put(id, data); 
returnToUrl += "?token=" + URLEncoder.encode(id, "UTF-8"); 
// ... 

Y luego, cuando se trata atrás, use HttpServletRequestWrapper para envolver la petición actual en la que se anula la getParameter() y consortes para devolver los datos originales de interés. Haz esto en un Filter.

String id = request.getParameter(token); 
Map<String, DataOfInterest> map = (Map<String, DataOfInterest) session.getAttribute("dataOfInterest"); 
DataOfInterest data = map.remove(id); 
chain.doFilter(new HttpServletRequestWithDataOfInterest(request, data), response); 

El HttpServletRequestWithDataOfInterest podría tener este aspecto:

public class HttpServletRequestWithDataOfInterest extends HttpServletRequestWrapper { 

    private DataOfInterest data; 

    public HttpServletRequestWithDataOfInterest(HttpServletRequest request, DataOfInterest data) { 
     super(request); 
     this.data = data; 
    } 

    public String getParameter(String name) { 
     return data.getParameter(name); 
    } 

    public String[] getParameterValues(String name) { 
     return data.getParameterValues(name); 
    } 

    // Etc, only when necessary. 
} 

Nota: Cualquier manipulación nullcheck obvia etc depende de usted.

+0

Nunca supe de HttpServletRequestWrapper: suena como el cableado que necesito. – jricher

+0

De nada. – BalusC

1

No, no puedes guardar una solicitud. Pero puede hacer que su filtro cree una sesión y agregue el objeto al alcance de la sesión. Los objetos que tienen acceso a la sesión pueden usar cualquier objeto que encuentren.

2

Para uso general, sería más complejo que guardar solo un cuerpo de solicitud, también debe guardar encabezados, etc.

Puede marcar how it's implemented in Spring Security.

+0

Eso es cierto, así que esperaba simplemente guardar el objeto de solicitud anterior directamente y cortocircuitar cualquier análisis. – jricher

0

Por lo que vale (y para cualquiera que venga aquí en el futuro), después de luchar con esto por otra semana, terminé cambiando mi aplicación para usar Spring Security por completo en vez de un filtro personalizado independiente y funciona estupendo. El marco de Spring Security maneja muchos de los problemas ocasionales con los redireccionamientos y las solicitudes pospuestas que comencé a tener que escribir por mi cuenta.

Gracias a todos por sus sugerencias.

Cuestiones relacionadas