web-dev-qa-db-fra.com

Client Jersey: Ajout de cookies à la demande

J'essaie d'écrire une bibliothèque qui accède à un service Web reposant à l'aide de l'API client Jersey. Le service nécessite une demande de connexion qui définit un cookie, puis les demandes suivantes doivent avoir ce cookie pour réussir. La demande de connexion fonctionne comme prévu et je suis capable de récupérer le cookie dans la réponse de la connexion, mais ne peut sembler ajouter le cookie dans les demandes suivantes. Est-ce que quelqu'un peut dire ce que je vais faire de mal. Voici le code qui fait la demande:

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 );

Bien que la demande n'échoue pas, le service répond avec l'erreur de l'application "Aucune session". Voici la trace de journal de la séquence de demande:

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]

Je pense que la demande suivante doit avoir les cookies dans l'en-tête:

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>

Toute directive à ce sujet est très appréciée.

17
pconrey

Le problème est Webresource est immuable - la méthode de la cookie () renvoie webresource.builder. Donc, faire ce qui suit crée simplement une nouvelle instance de webresource.builder chaque fois que vous appelez Cookie (et ne modifie pas le tout à la webreResource d'origine). Vous ignorez ces instances de constructeur et effectuez toujours la demande sur la webreResource d'origine:

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

Vous devriez faire ce qui suit à la place:

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

Ensuite, vous pouvez faire la demande en:

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

De plus, pour éviter de faire dupliquer ce code dans toutes vos méthodes de ressources, vous voudrez peut-être envisager de rédiger un filtre client, qui le fera pour vous pour toutes vos demandes. Par exemple. Le code suivant garantirait des cookies envoyés à partir du serveur GET SET pour chaque réponse:

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;
    }
});

Remarque: cela ne fonctionnera que si vous ne partagez pas les instances client avec plusieurs threads!

26
Martin Matula

J'ai constaté qu'un moyen plus simple d'assurer que les cookies soient renvoyés consiste à utiliser l'intégration du client HTTP Apache HTTP de Jersey-Client. Il se trouve dans le package Maven Jersey-Apache-Client-Client:

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

Vous pouvez alors faire:

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

À partir de ce moment, continuez simplement à utiliser le même client sur les demandes et les cookies seront collectés et renvoyés au serveur comme prévu.

9
Emmanuel Touzery

Peut-être avez-vous besoin d'adapter les cookies dans un appel WeBresource qui travaillait auparavant sans eux. Ensuite, vous vous retrouverez peut-être enfreindre votre ligne de code que vous pouvez travailler avec la partie intégrante. Pour inclure des cookies, votre code pourrait aller de:

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

À:

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);
3
Jerry Frost