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 Restful Web Services (jax rs) 身份验证模式