Клиент Джерси: добавление файлов cookie по запросу - PullRequest
16 голосов
/ 16 июля 2011

Я пытаюсь написать библиотеку, которая обращается к веб-службе RESTful, используя клиентский API Jersey.Служба требует запроса входа в систему, который устанавливает cookie, тогда последующие запросы должны иметь этот cookie для успешной работы.Запрос на вход в систему работает, как и ожидалось, и я могу получить cookie в ответе от имени входа, но, похоже, не могу добавить cookie обратно в последующих запросах.Может кто-нибудь сказать, что я могу делать не так.Вот код, который делает запрос:

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

Пока запрос не завершается неудачно, служба отвечает сообщением об ошибке «Нет сеанса».Вот журнал трассировки последовательности запросов:

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]

Я думаю, что следующий запрос должен содержать файлы cookie в заголовке:

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>

Любое руководство по этому вопросу высоко ценится.

Ответы [ 3 ]

25 голосов
/ 18 сентября 2011

Проблема в том, что WebResource неизменен - ​​метод cookie () возвращает WebResource.Builder. Таким образом, выполнение следующих действий просто создает новый экземпляр WebResource.Builder каждый раз, когда вы вызываете cookie (и вообще не изменяет исходный WebResource). Вы игнорируете эти экземпляры Builder и по-прежнему выполняете запрос на исходном WebResource:

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

Вместо этого вы должны сделать следующее:

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

Затем вы можете сделать запрос:

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

Кроме того, чтобы избежать дублирования этого кода во всех ваших ресурсных методах, вы можете рассмотреть возможность написания клиентского фильтра, который сделает это за вас для всех ваших запросов. Например. следующий код гарантирует, что куки, отправленные с сервера, будут установлены для каждого ответа:

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

ПРИМЕЧАНИЕ. Это будет работать только в том случае, если вы не делитесь экземплярами клиента с несколькими потоками!

9 голосов
/ 14 марта 2013

Я обнаружил, что более простой способ обеспечить отправку файлов cookie - это использовать HTTP-клиент Apache для интеграции с клиентом jersey-client.Он находится в пакете maven jersey-apache-client:

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

Затем вы можете выполнить:

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

С этого момента просто продолжайте использовать один и тот же клиент для запросов икуки будут собраны и отправлены обратно на сервер, как и ожидалось.

3 голосов
/ 19 января 2012

Возможно, вам нужно вставить куки в вызов WebResource, который раньше работал без них.Тогда вы, возможно, обнаружите, что разбиваете строку кода, с которой вы можете работать вместе со сборщиком.Чтобы включить файлы cookie, ваш код может содержать:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...