Jersey jax.rs 客户端 2.5 遵循从 HTTP 到 HTTPS 的重定向

Posted

技术标签:

【中文标题】Jersey jax.rs 客户端 2.5 遵循从 HTTP 到 HTTPS 的重定向【英文标题】:Jersey jax.rs client 2.5 follow redirect from HTTP to HTTPS 【发布时间】:2014-03-13 18:10:12 【问题描述】:

我有一个设置,其中托管我的 REST 服务器的 tomcat 服务器将调用从 HTTP(端口 9080)重定向到 HTTPS(端口 9443)。

我正在使用 jersey 2.5 实现,无法配置客户端以遵循重定向。

我发现了这个 SO 问题 (Jersey client doesn't follow redirects),但是它是为 jersey 1.X 系列提供的,并且 API 已更改。

我尝试使用以下测试代码使其适应 2.5:

 SSLContextProvider ssl = new TrustAllSSLContextImpl(); // just trust all certs
 Response response  =     ClientBuilder.newBuilder()
     .sslContext(ssl.getContext()).newClient()
     .register(LoggingFilter.class)
     .target("http://testhost.domain.org:9080/rest.webapp/api/v1/hello/")
     .property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE)
     .request().get();   
 Assertions.assertThat(response.getStatus()).isNotEqualTo(302);

由于客户端似乎没有遵循重定向而失败。以下是日志过滤器提供的内容:

Feb 14, 2014 12:23:45 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Sending client request on thread main
1 > GET http://testhost.domain.org:9080/rest.webapp/api/v1/hello/

Feb 14, 2014 12:23:45 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Client response received on thread main
1 < 302
1 < Cache-Control: private
1 < Content-Length: 0
1 < Date: Fri, 14 Feb 2014 11:38:59 GMT
1 < Expires: Thu, 01 Jan 1970 01:00:00 CET
1 < Location: https://testhost.domain.org:9443/rest.webapp/api/v1/hello/
1 < Server: Apache-Coyote/1.1

从球衣文档中,我了解到需要做的就是将 ClientProperties.FOLLOW_REDIRECTS 属性添加到客户端,但这显然不是这种情况。我还发现消息表明可能是客户端过滤器需要遵循重定向,但没有找到这方面的示例或指南。

因此,如果有人对 jax.rs 和重定向有一定的经验,可以向我指出一些方向/文档/示例代码,我将不胜感激。

【问题讨论】:

【参考方案1】:

发生这种情况是因为如果 URL 方案在重定向期间发生更改,Http(s)UrlConnection 不遵循重定向(参见例如HTTPURLConnection Doesn't Follow Redirect from HTTP to HTTPS)。所以可能的解决方案是use alternative client transport connector。

这可能看起来像

SSLContextProvider ssl = new TrustAllSSLContextImpl(); // just trust all certs

JerseyClientBuilder clientBuilder = new JerseyClientBuilder()
 .sslContext(ssl.getContext())
 .register(LoggingFilter.class);
clientBuilder.getConfiguration().connectorProvider(new org.glassfish.jersey.apache.connector.ApacheConnectorProvider());

JerseyClient client = clientBuilder.build();

Response response = client    
 .target("http://testhost.domain.org:9080/rest.webapp/api/v1/hello/")
 .property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE)
 .request().get();
Assertions.assertThat(response.getStatus()).isNotEqualTo(302);

【讨论】:

【参考方案2】:

正确的做法是:

webTarget.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE);

【讨论】:

你确定最后一个参数是 "false" 吗?在我看来,这只是禁用重定向:) 这应该是webTarget.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE),正如之前的评论者所指出的那样。 这只适用于泽西岛; ClientProperties 是一个 Jersey 类。 JAX-RS 尚未指定任何重定向处理选项 这是错误的;这只会在协议更改时启用重定向,而不是重定向 HTTP->HTTPS。此外,无论如何,此设置已经默认为“true”。 -1 因为这只是球衣,但原作者明确要求 JAX-RS(这是他目前正在使用的球衣实现的标准)。【参考方案3】:

好吧,我终于用过滤器解决了这个问题,不确定这是最好的解决方案,感谢任何 cmets:

public class FollowRedirectFilter implements ClientResponseFilter

   @Override
   public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException
   
      if (responseContext.getStatusInfo().getFamily() != Response.Status.Family.REDIRECTION)
         return;

      Response resp = requestContext.getClient().target(responseContext.getLocation()).request().method(requestContext.getMethod());

      responseContext.setEntityStream((InputStream) resp.getEntity());
      responseContext.setStatusInfo(resp.getStatusInfo());
      responseContext.setStatus(resp.getStatus());
   

【讨论】:

我在这里找到了答案***.com/questions/1884230/…:出于安全原因,从 http 到 https 的重定向不起作用。 不要忘记 a) 在客户端用 @javax.ws.rs.ext.Provider 和 b) register 注释过滤器。 @FrankNeblung:根据注册方式,可能不需要注释。但它肯定需要向 JAX-RS 注册。 虽然这在成功遵循重定向的意义上确实有效,但它存在一些问题。当我尝试使用它时, response.getMediaType() 返回的 Content-Type 是第一个请求返回的 Content-Type,而不是重定向请求。因此,像这样重用 ResponseContext 似乎不是一个干净的解决方案。

以上是关于Jersey jax.rs 客户端 2.5 遵循从 HTTP 到 HTTPS 的重定向的主要内容,如果未能解决你的问题,请参考以下文章

Java-泽西岛,JAX RS

Java Restful Web Services (jax rs) 身份验证模式

在 Jax Rs / Appfuse 应用程序中获取 HttpServletRequest?

jax rs像param一样的多维数组

WebService

webservice 开发规范