RestTemplate客户端与cookie

Tom*_*Tom 15 java cookies spring http resttemplate

我正在用Java编写一个简单的客户端,以允许可重用​​使用通过RESTful API访问的专有病毒扫描软件.要上传用于扫描API的文件,需要使用POSTfor Connect,然后使用POSTfor将文件发布到服务器.在对Connect的响应中,POST服务器设置了cookie,后者需要在POST发布文件时使用.我目前正在RestTemplate我的客户端使用Spring .

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

Ily*_*nko 16

我通过创建一个拦截器解决了这个问题,该拦截器存储一个 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

为您的 RestTemplate 设置拦截器:

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

  • 注意 `RestTemplateBuilder` 仅存在于 `spring-boot` 中。还可以直接在“RestTemplate”对象上使用“setInterceptors(new StatefulRestTemplateInterceptor)”,仅供阅读本文的人注意。不过,解决方案就像一个魅力。 (2认同)

Koi*_*oer 13

RestTemplate有一个方法可以定义接口ResponseExtractor<T>,这个接口用于获取响应的标题,一旦你有它,你可以使用它HttpEntity再发送它.

 .add("Cookie", "SERVERID=c52");
Run Code Online (Sandbox Code Playgroud)

尝试这样的事情.

String cookieHeader = null;

new ResponseExtractor<T>(){
      T extractData(ClientHttpResponse response) {
        response.getHeaders();
      }
}
Run Code Online (Sandbox Code Playgroud)

然后

  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);
Run Code Online (Sandbox Code Playgroud)

也阅读这篇文章


小智 9

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

@谢谢谢登

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 /sf/ask/1599732501/
 */
@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);
            }
        });
    }

}
Run Code Online (Sandbox Code Playgroud)


viv*_*348 7

它可以像浏览器使用下面的代码一样自动实现。

参考:1.https: //hc.apache.org/httpclient-3.x/cookies.html

  1. https://hc.apache.org/httpcomponents-client-ga/tutorial/html/statemgmt.html
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
    RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build();        
    HttpClient  httpClient = HttpClientBuilder.create()
            .setDefaultRequestConfig(requestConfig)         
            .build();   
    
    RestTemplate restTemplate = restTemplateBuilder
            .requestFactory(
                    () -> {
                        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
                        requestFactory.setHttpClient(httpClient);
                        return new BufferingClientHttpRequestFactory(requestFactory);
                    })
            .basicAuthentication("username", "password")
            .build();
    
    return restTemplate;
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这比该线程中的大多数替代方案效果更好。 (2认同)

Jav*_*Pro 5

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

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