2011-07-15 19 views
15

Estoy intentando escribir una biblioteca que accede a un servicio web RESTful utilizando la API de Jersey Client. El servicio requiere una solicitud de inicio de sesión que establece una cookie, luego las solicitudes posteriores deben tener esa cookie configurada para tener éxito. La solicitud de inicio de sesión funciona como se esperaba, y puedo recuperar la cookie en la respuesta desde el inicio de sesión, pero parece que no puedo volver a agregar la cookie en las solicitudes posteriores. ¿Alguien puede decir lo que podría estar haciendo mal? Aquí está el código que realiza la solicitud:Jersey Client: Agregar cookies a la solicitud

MultivaluedMap<String,String> qs = new MultivaluedMapImpl(); 
qs.add("xml", this.toXmlString()); 

WebResource wr = client.resource(Constants.ServiceURL);  
if (CookieJar.Cookies != null) 
{ 
    for (NewCookie c : CookieJar.Cookies) 
    { 
    logger.debug("Setting cookie " + c.getName()); 
    wr.cookie(c); 
    } 
} 

ClientResponse response = wr.queryParams(qs).get(ClientResponse.class); 

Mientras que la solicitud no falla, el servicio responde con el error de aplicación "Sin Sesión". Aquí está el registro de seguimiento de la secuencia de solicitud:

Jul 15, 2011 5:20:33 PM com.sun.jersey.api.client.filter.LoggingFilter log 
INFO: 1 * Client out-bound request 
1 > GET https://www.company.com/TrackerXMLInterface.asp?xml=%3Cxml%3E%3CTRANTYPE%3ELOGIN%3C/TRANTYPE%3E%3CTRANPARMS%3E%3CLOGINID%3Emylogin%3C/LOGINID%3E%3CPASSPHRASE%3EBa1b2c3%3C/PASSPHRASE%3E%3C/TRANPARMS%3E%3C/xml%3E 

Jul 15, 2011 5:20:35 PM com.sun.jersey.api.client.filter.LoggingFilter log 
INFO: 1 * Client in-bound response 
1 < 200 
1 < Date: Fri, 15 Jul 2011 22:20:35 GMT 
1 < Content-Length: 150 
1 < Set-Cookie: ASPSESSIONIDSUBSBSRR=GBGOKGJDAAHCNDDHPBFICFIH; secure; path=/ 
1 < Content-Type: text/html 
1 < Server: Microsoft-IIS/7.0 
1 < X-Powered-By: ASP.NET 
1 < Cache-Control: private 
1 < 
<XML><TRANRESULTS><TRANRETURNCODE>L00</TRANRETURNCODE><TRANRETURNMSG>Valid Login   </TRANRETURNMSG><TRANDETAIL></TRANDETAIL></TRANRESULTS></XML> 
[continued below] 

Estoy pensando en la siguiente petición debe tener las cookies en la cabecera:

Jul 15, 2011 5:20:35 PM com.sun.jersey.api.client.filter.LoggingFilter log 
INFO: 1 * Client out-bound request 
1 > GET https://www.company.com/TrackerXMLInterface.asp?xml=%3Cxml%3E%3CTRANTYPE%3ESSNLAST%3C/TRANTYPE%3E%3CTRANPARMS%3E%3CSSN%3E123456789%3C/SSN%3E%3CLASTNAME%3ESchmoe%3C/LASTNAME%3E%3C/TRANPARMS%3E%3C/xml%3E 

Jul 15, 2011 5:20:35 PM com.sun.jersey.api.client.filter.LoggingFilter log 
INFO: 1 * Client in-bound response 
1 < 200 
1 < Date: Fri, 15 Jul 2011 22:20:35 GMT 
1 < Content-Length: 150 
1 < Set-Cookie: ASPSESSIONIDSUBSBSRR=HBGOKGJDIAPBBEIGLOILDJDN; secure; path=/ 
1 < Content-Type: text/html 
1 < Server: Microsoft-IIS/7.0 
1 < X-Powered-By: ASP.NET 
1 < Cache-Control: private 
1 < 
<XML><TRANRESULTS><TRANRETURNCODE>R04</TRANRETURNCODE><TRANRETURNMSG>No Session   </TRANRETURNMSG><TRANDETAIL></TRANDETAIL></TRANRESULTS></XML> 

Cualquier orientación al respecto es muy apreciada.

Respuesta

24

El problema es que WebResource es inmutable: el método cookie() devuelve WebResource.Builder. Por lo tanto, al hacer lo siguiente solo crea una nueva instancia de WebResource.Builder cada vez que llama a una cookie (y no modifica la fuente web original en absoluto). Se ignora aquellos casos Builder y aún realizar la solicitud en el WebResource el original:

for (NewCookie c : CookieJar.Cookies) { 
    logger.debug("Setting cookie " + c.getName()); 
    wr.cookie(c); 
} 

debe hacer lo siguiente en su lugar:

WebResource.Builder builder = wr.getRequestBuilder(); 
for (NewCookie c : CookieJar.Cookies) { 
    builder = builder.cookie(c); 
} 

entonces puede presentar la solicitud por:

ClientResponse response = builder.queryParams(qs).get(ClientResponse.class); 

Además, para evitar la duplicación de este código en todos sus métodos de recursos, le recomendamos que escriba un filtro de cliente, que lo hará por usted para todas sus solicitudes. P.ej. el siguiente código aseguraría cookies enviadas desde el servidor Prepárese para cada respuesta:

client.addFilter(new ClientFilter() { 
    private ArrayList<Object> cookies; 

    @Override 
    public ClientResponse handle(ClientRequest request) throws ClientHandlerException { 
     if (cookies != null) { 
      request.getHeaders().put("Cookie", cookies); 
     } 
     ClientResponse response = getNext().handle(request); 
     if (response.getCookies() != null) { 
      if (cookies == null) { 
       cookies = new ArrayList<Object>(); 
      } 
      // simple addAll just for illustration (should probably check for duplicates and expired cookies) 
      cookies.addAll(response.getCookies()); 
     } 
     return response; 
    } 
}); 

NOTA: Esto sólo funcionará si usted no comparte las instancias de cliente con múltiples hilos!

+1

salvó mis pruebas, gracias –

+0

no funcionó para mí, incluso después de la fijación –

3

Quizás necesite insertar cookies en una llamada a WebResource que haya estado trabajando previamente sin ellas. Entonces puede que se rompa la línea de código con la que puede trabajar con el constructor a mitad de camino. Para incluir cookies, su código podría ir desde:

clientResponse = webResource.queryParams(parameters).type(httpContentType).accept(httpAcceptType).post(ClientResponse.class, requestBody); 

a:

builder = webResource.queryParams(parameters).type(httpContentType); 
if (cookieJar != null) 
{ 
    for (Cookie c : cookieJar) 
     builder = builder.cookie(c); 
} 
clientResponse = builder.accept(httpAcceptType).post(ClientResponse.class, requestBody); 
6

He encontrado que una manera más sencilla para asegurar las cookies son enviados de vuelta es utilizar la integración del cliente HTTP Apache de Jersey- cliente. Se encuentra en el paquete experto Jersey-Apache-cliente:

<dependency> 
    <groupId>com.sun.jersey.contribs</groupId> 
    <artifactId>jersey-apache-client</artifactId> 
    <version>1.13</version> 
    <type>jar</type> 
</dependency> 

A continuación, puede hacer:

ApacheHttpClientConfig config = new DefaultApacheHttpClientConfig(); 
config.getProperties().put(ApacheHttpClientConfig.PROPERTY_HANDLE_COOKIES, true); 
ApacheHttpClient client = ApacheHttpClient.create(config); 

A partir de entonces, sólo seguir utilizando el mismo cliente a través de solicitudes y se recogerán las galletas y enviado de vuelta al servidor como se esperaba.

+0

parece que este enfoque solo es compatible con Jersey v1 – harschware

Cuestiones relacionadas