RestTemplate客户端与cookie

时间:2014-04-04 04:03:30

标签: java spring http cookies resttemplate

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

我的问题是如何访问响应中的cookie以使用后续POST转发回服务器?我可以看到它们出现在返回的标题中,但ResponseEntity上没有方法可以访问它们。

9 个答案:

答案 0 :(得分:9)

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

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

尝试这样的事情。

String cookieHeader = null;

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

然后

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

另请阅读此post

答案 1 :(得分:3)

您需要使用Java Spring框架exchange的{​​{1}}方法。

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

答案 2 :(得分:2)

使用'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);
            }
        });
    }

}

答案 3 :(得分:2)

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

参考: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;
}

答案 4 :(得分:1)

我写了一个扩展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);
            }
        });
    }

}

答案 5 :(得分:1)

我已经通过创建一个拦截器来解决该问题,该拦截器存储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;
    }
}

为RestTemplate设置拦截器:

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

答案 6 :(得分:0)

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

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

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

答案 7 :(得分:0)

                    package zuulx;

                import java.net.URI;
                import java.net.URISyntaxException;

                import org.springframework.http.HttpEntity;
                import org.springframework.http.HttpHeaders;
                import org.springframework.http.HttpMethod;
                import org.springframework.http.ResponseEntity;
                import org.springframework.web.client.RestTemplate;

                public class CookieTest {
                /**
                 * 
                 * array(1) {
                  ["aaa"]=>
                  string(2) "11"
                }


                 * @param args
                 * @throws URISyntaxException
                 */
                    public static void main(String[] args) throws URISyntaxException {
                        
                        HttpHeaders headers = new HttpHeaders();
                          headers.add("Cookie", "aaa=11" );
                          
                        
                           RestTemplate restTemplate = new RestTemplate();
                           
                    //  URI url= new URI("http://localhost:9088/cktest");
                    //  System.out.println( restTemplate.getForObject(url, String.class));  
                        
                          String url = "http://localhost/showck.php";
                          url="http://localhost:9088/cktest";
                        ResponseEntity response = restTemplate.exchange(url,
                                  HttpMethod.GET,
                                  new HttpEntity (headers) ,String.class);
                          
                          System.out.println(response.getBody());
                        
                        
                        //http://localhost/showck.php

                    }

                }

答案 8 :(得分:0)

使用 Cookie 调用 RestTemplate 的代码片段

        final String url = "url";
        String set_cookie = "cookie value";

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Cookie", set_cookie);
        HttpEntity request = new HttpEntity(headers);
        
        ResponseEntity<Profile> response = restTemplate.exchange(url, HttpMethod.GET, request, Profile.class);