Java 带有 cookie 的 RestTemplate 客户端

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22853321/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 18:23:38  来源:igfitidea点击:

RestTemplate client with cookies

javaspringhttpcookiesresttemplate

提问by Tom

I'm writing a simple client in Java to allow reusable use of proprietary virus scanning software accessible through a RESTful API. To upload a file for scanning the API requires a POSTfor Connect, followed by a POSTfor Publishing the file to the server. In the response to the Connect POSTthere are cookies set by the server which need to be present in the subsequent POSTfor publishing the file. I'm currently using Spring RestTemplatein my client.

我正在用 Java 编写一个简单的客户端,以允许重复使用可通过 RESTful API 访问的专有病毒扫描软件。上传文件扫描 API 需要一个POSTfor Connect,然后是一个POSTfor Publishing the file to the server。在对 Connect 的响应中,POST服务器设置了 cookie,这些 cookie 需要出现在后续POST发布文件中。我目前RestTemplate在我的客户端中使用 Spring 。

My question is how do I access the cookies in the response to forward back to the server with the subsequent POST? I can see that they are present in the header that is returned but there are no methods on the ResponseEntityto access them.

我的问题是如何访问响应中的 cookie 以将其转发回服务器POST?我可以看到它们存在于返回的标头中,但没有方法ResponseEntity可以访问它们。

采纳答案by Koitoer

RestTemplatehas a method in which you can define Interface ResponseExtractor<T>, this interface is used to obtain the headers of the response, once you have them you could send it back using HttpEntityand added again.

RestTemplate有一个方法,您可以在其中定义 Interface ResponseExtractor<T>,该接口用于获取响应的标头,一旦拥有它们,您就可以将其发送回去HttpEntity并再次添加。

 .add("Cookie", "SERVERID=c52");

Try something like this.

尝试这样的事情。

String cookieHeader = null;

new ResponseExtractor<T>(){
      T extractData(ClientHttpResponse response) {
        response.getHeaders();
      }
}

Then

然后

  HttpHeaders headers = new HttpHeaders();
  headers.add("Cookie", cookieHeader );

  ResponseEntity<byte[]> response = restTemplate.exchange("http://example.com/file/123",
      GET,
      new HttpEntity<String>(headers),
      byte[].class);

Also read this post

还阅读了这篇文章

回答by user5495300

You need to use exchangemethod of RestTemplateof Java Spring framework.

您需要使用exchange的方法RestTemplate的Java Spring框架的。

Read this tutorial: http://codeflex.co/java-rest-client-get-cookie/

阅读本教程:http: //codeflex.co/java-rest-client-get-cookie/

回答by Shedon

i've wrote a simple class that extends RestTemplate and handles cookies.

我写了一个简单的类,它扩展了 RestTemplate 并处理 cookie。

import java.io.IOException;
import java.net.URI;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

public class RestTemplateWithCookies extends RestTemplate {

    private List<String> cookies = null;

    public RestTemplateWithCookies() {
    }

    public RestTemplateWithCookies(ClientHttpRequestFactory requestFactory) {
        super(requestFactory);
    }

    private synchronized List<String> getCoookies() {
        return cookies;
    }

    private synchronized void setCoookies(List<String> cookies) {
        this.cookies = cookies;
    }

    public synchronized void resetCoookies() {
        this.cookies = null;
    }

    private void processHeaders(HttpHeaders headers) {
        final List<String> cookies = headers.get("Set-Cookie");
        if (cookies != null && !cookies.isEmpty()) {
            setCoookies(cookies);
        }
    }

    @Override
    protected <T extends Object> T doExecute(URI url, HttpMethod method, final RequestCallback requestCallback, final ResponseExtractor<T> responseExtractor) throws RestClientException {
        final List<String> cookies = getCoookies();

        return super.doExecute(url, method, new RequestCallback() {
            @Override
            public void doWithRequest(ClientHttpRequest chr) throws IOException {
                if(cookies != null) {
                    for(String cookie : cookies) {
                        chr.getHeaders().add("Cookie", cookie);
                    }
                }
                requestCallback.doWithRequest(chr);
            }

        }, new ResponseExtractor<T>() {
            @Override
            public T extractData(ClientHttpResponse chr) throws IOException {
                processHeaders(chr.getHeaders());
                return responseExtractor.extractData(chr);
            }
        });
    }

}

回答by GerardNorton

Small update to handle sessions in a complete test with 'java.net.HttpCookie' Object.

使用“java.net.HttpCookie”对象在完整测试中处理会话的小更新。

@Thanks Shedon

@谢谢谢登

import java.io.IOException;
import java.net.HttpCookie;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

/**
 * @link https://stackoverflow.com/questions/22853321/resttemplate-client-with-cookies
 */
@Component
public class RestTemplateWithCookies extends RestTemplate {

    private final List<HttpCookie> cookies = new ArrayList<>();

    public RestTemplateWithCookies() {
    }

    public RestTemplateWithCookies(ClientHttpRequestFactory requestFactory) {
        super(requestFactory);
    }

    public synchronized List<HttpCookie> getCoookies() {
        return cookies;
    }

    public synchronized void resetCoookies() {
        cookies.clear();
    }

    private void processHeaders(HttpHeaders headers) {
        final List<String> cooks = headers.get("Set-Cookie");
        if (cooks != null && !cooks.isEmpty()) {
            cooks.stream().map((c) -> HttpCookie.parse(c)).forEachOrdered((cook) -> {
                cook.forEach((a) -> {
                    HttpCookie cookieExists = cookies.stream().filter(x -> a.getName().equals(x.getName())).findAny().orElse(null);
                    if (cookieExists != null) {
                        cookies.remove(cookieExists);
                    }
                    cookies.add(a);
                });
            });
        }
    }

    @Override
    protected <T extends Object> T doExecute(URI url, HttpMethod method, final RequestCallback requestCallback, final ResponseExtractor<T> responseExtractor) throws RestClientException {
        final List<HttpCookie> cookies = getCoookies();

        return super.doExecute(url, method, new RequestCallback() {
            @Override
            public void doWithRequest(ClientHttpRequest chr) throws IOException {
                if (cookies != null) {
                    StringBuilder sb = new StringBuilder();
                    for (HttpCookie cookie : cookies) {
                        sb.append(cookie.getName()).append(cookie.getValue()).append(";");
                    }
                    chr.getHeaders().add("Cookie", sb.toString());
                }
                requestCallback.doWithRequest(chr);
            }

        }, new ResponseExtractor<T>() {
            @Override
            public T extractData(ClientHttpResponse chr) throws IOException {
                processHeaders(chr.getHeaders());
                return responseExtractor.extractData(chr);
            }
        });
    }

}

回答by Ilya Lysenko

I've solved the problem by creating an interceptor which stores a cookie and puts it in next requests.

我通过创建一个拦截器解决了这个问题,该拦截器存储一个 cookie 并将其放入下一个请求中。

public class StatefulRestTemplateInterceptor implements ClientHttpRequestInterceptor {
    private String cookie;

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        if (cookie != null) {
            request.getHeaders().add(HttpHeaders.COOKIE, cookie);
        }
        ClientHttpResponse response = execution.execute(request, body);

        if (cookie == null) {
            cookie = response.getHeaders().getFirst(HttpHeaders.SET_COOKIE);
        }
        return response;
    }
}

Set the interceptor for your RestTemplate:

为您的 RestTemplate 设置拦截器:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder templateBuilder) {
    return templateBuilder
            .requestFactory(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory()))
            .interceptors(new StatefulRestTemplateInterceptor())
            .build();
}

回答by DAN

To get more browser like behavior you can use this interceptor:

要获得更多类似浏览器的行为,您可以使用此拦截器:

import java.io.IOException;
import java.net.HttpCookie;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class CookieHandlingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

  private static final Logger LOG = LoggerFactory.getLogger(CookieHandlingClientHttpRequestInterceptor.class);

  private final Map<String, HttpCookie> cookies = new HashMap<>();

  @Override
  public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
    List<String> cookiesForRequest = cookies.values().stream()
        .filter(cookie -> cookie.getPath() != null && request.getURI().getPath().startsWith(cookie.getPath()))
        .map(HttpCookie::toString)
        .collect(Collectors.toList());
    LOG.info("Using cookies: {}", cookiesForRequest);
    request.getHeaders().addAll(HttpHeaders.COOKIE, cookiesForRequest);

    ClientHttpResponse response = execution.execute(request, body);

    List<String> newCookies = response.getHeaders().get(HttpHeaders.SET_COOKIE);
    if (newCookies != null) {
      List<HttpCookie> parsedCookies = newCookies.stream().flatMap(rawCookie -> HttpCookie.parse(HttpHeaders.SET_COOKIE + ": " + rawCookie).stream()).collect(Collectors.toList());
      LOG.info("Extracted cookies from response: {}", parsedCookies);
      parsedCookies.forEach(newCookie -> cookies.put(newCookie.getName(), newCookie));
    }

    return response;
  }
}

And keep in mind that by default RestTemplate follows redirects for GET requests. In this case the above interceptor is bypassed.

请记住,默认情况下 RestTemplate 遵循 GET 请求的重定向。在这种情况下,上述拦截器被绕过。