Skip to content

Commit 62abe73

Browse files
agherardijansupol
authored andcommitted
Fixed connection leak in basic and digest authenticators if 401 response has content (#3878)
Signed-off-by: agherardi <[email protected]>
1 parent 0c341a3 commit 62abe73

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import org.glassfish.jersey.client.ClientConfig;
3737
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
38+
import org.glassfish.jersey.client.authentication.ResponseAuthenticationException;
3839
import org.glassfish.jersey.server.ResourceConfig;
3940
import org.glassfish.jersey.test.JerseyTest;
4041

@@ -47,6 +48,7 @@
4748
import static org.junit.Assert.assertEquals;
4849
import static org.junit.Assert.assertNotNull;
4950
import static org.junit.Assert.assertTrue;
51+
import static org.junit.Assert.fail;
5052

5153
/**
5254
* @author Paul Sandoz
@@ -248,6 +250,40 @@ public String deleteFilterWithEntity(@Context HttpHeaders h, String e) {
248250
return e;
249251
}
250252

253+
@GET
254+
@Path("content")
255+
public String getWithContent(@Context HttpHeaders h) {
256+
requestCount++;
257+
String value = h.getRequestHeaders().getFirst("Authorization");
258+
if (value == null) {
259+
assertEquals(1, requestCount);
260+
throw new WebApplicationException(
261+
Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"")
262+
.entity("Forbidden").build());
263+
} else {
264+
assertTrue(requestCount > 1);
265+
}
266+
267+
return "GET";
268+
}
269+
270+
@GET
271+
@Path("contentDigestAuth")
272+
public String getWithContentDigestAuth(@Context HttpHeaders h) {
273+
requestCount++;
274+
String value = h.getRequestHeaders().getFirst("Authorization");
275+
if (value == null) {
276+
assertEquals(1, requestCount);
277+
throw new WebApplicationException(
278+
Response.status(401).header("WWW-Authenticate", "Digest nonce=\"1234\"")
279+
.entity("Forbidden").build());
280+
} else {
281+
assertTrue(requestCount > 1);
282+
}
283+
284+
return "GET";
285+
}
286+
251287
@GET
252288
@Path("queryParamsBasic")
253289
public String getQueryParamsBasic(@Context HttpHeaders h, @Context UriInfo uriDetails) {
@@ -455,6 +491,52 @@ public void testAuthInteractivePost() {
455491
assertEquals("POST", r.request().post(Entity.text("POST"), String.class));
456492
}
457493

494+
@Test
495+
public void testAuthGetWithBasicFilterAndContent() {
496+
ClientConfig cc = new ClientConfig();
497+
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
498+
cc.connectorProvider(new ApacheConnectorProvider());
499+
cc.property(ApacheClientProperties.CONNECTION_MANAGER, cm);
500+
Client client = ClientBuilder.newClient(cc);
501+
client.register(HttpAuthenticationFeature.universalBuilder().build());
502+
WebTarget r = client.target(getBaseUri()).path("test/content");
503+
504+
try {
505+
assertEquals("GET", r.request().get(String.class));
506+
fail();
507+
} catch (ResponseAuthenticationException ex) {
508+
// expected
509+
}
510+
511+
// Verify the connection that was used for the request is available for reuse
512+
// and no connections are leased
513+
assertEquals(cm.getTotalStats().getAvailable(), 1);
514+
assertEquals(cm.getTotalStats().getLeased(), 0);
515+
}
516+
517+
@Test
518+
public void testAuthGetWithDigestFilterAndContent() {
519+
ClientConfig cc = new ClientConfig();
520+
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
521+
cc.connectorProvider(new ApacheConnectorProvider());
522+
cc.property(ApacheClientProperties.CONNECTION_MANAGER, cm);
523+
Client client = ClientBuilder.newClient(cc);
524+
client.register(HttpAuthenticationFeature.universalBuilder().build());
525+
WebTarget r = client.target(getBaseUri()).path("test/contentDigestAuth");
526+
527+
try {
528+
assertEquals("GET", r.request().get(String.class));
529+
fail();
530+
} catch (ResponseAuthenticationException ex) {
531+
// expected
532+
}
533+
534+
// Verify the connection that was used for the request is available for reuse
535+
// and no connections are leased
536+
assertEquals(cm.getTotalStats().getAvailable(), 1);
537+
assertEquals(cm.getTotalStats().getLeased(), 0);
538+
}
539+
458540
@Test
459541
public void testAuthGetQueryParamsBasic() {
460542
ClientConfig cc = new ClientConfig();

core-client/src/main/java/org/glassfish/jersey/client/authentication/BasicAuthenticator.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ public boolean filterResponseAndAuthenticate(ClientRequestContext request, Clien
101101
.getCredentials(request, defaultCredentials, HttpAuthenticationFilter.Type.BASIC);
102102

103103
if (credentials == null) {
104+
if (response.hasEntity()) {
105+
AuthenticationUtil.discardInputAndClose(response.getEntityStream());
106+
}
104107
throw new ResponseAuthenticationException(null, LocalizationMessages.AUTHENTICATION_CREDENTIALS_MISSING_BASIC());
105108
}
106109

core-client/src/main/java/org/glassfish/jersey/client/authentication/DigestAuthenticator.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ public boolean filterResponse(final ClientRequestContext request, final ClientRe
125125
final HttpAuthenticationFilter.Credentials cred = HttpAuthenticationFilter.getCredentials(request,
126126
this.credentials, HttpAuthenticationFilter.Type.DIGEST);
127127
if (cred == null) {
128-
128+
if (response.hasEntity()) {
129+
AuthenticationUtil.discardInputAndClose(response.getEntityStream());
130+
}
129131
throw new ResponseAuthenticationException(null, LocalizationMessages.AUTHENTICATION_CREDENTIALS_MISSING_DIGEST());
130132
}
131133

0 commit comments

Comments
 (0)