diff --git a/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java b/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java index 3da55c1ade..dfbbbc1b53 100644 --- a/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java +++ b/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java @@ -53,6 +53,7 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import javax.inject.Singleton; @@ -140,6 +141,8 @@ public void testPreemptiveAuthPost() { public static class AuthResource { int requestCount = 0; + int queryParamsBasicRequestCount = 0; + int queryParamsDigestRequestCount = 0; @GET public String get(@Context HttpHeaders h) { @@ -229,6 +232,30 @@ public String deleteFilterWithEntity(@Context HttpHeaders h, String e) { return e; } + + @GET + @Path("queryParamsBasic") + public String getQueryParamsBasic(@Context HttpHeaders h, @Context UriInfo uriDetails) { + queryParamsBasicRequestCount++; + String value = h.getRequestHeaders().getFirst("Authorization"); + if (value == null) { + throw new WebApplicationException( + Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); + } + return "GET " + queryParamsBasicRequestCount; + } + + @GET + @Path("queryParamsDigest") + public String getQueryParamsDigest(@Context HttpHeaders h, @Context UriInfo uriDetails) { + queryParamsDigestRequestCount++; + String value = h.getRequestHeaders().getFirst("Authorization"); + if (value == null) { + throw new WebApplicationException( + Response.status(401).header("WWW-Authenticate", "Digest realm=\"WallyWorld\"").build()); + } + return "GET " + queryParamsDigestRequestCount; + } } @Test @@ -372,4 +399,34 @@ public void testAuthInteractivePost() { assertEquals("POST", r.request().post(Entity.text("POST"), String.class)); } + + @Test + public void testAuthGetQueryParamsBasic() { + ClientConfig cc = new ClientConfig(); + cc.connectorProvider(new ApacheConnectorProvider()); + Client client = ClientBuilder.newClient(cc); + client.register(HttpAuthenticationFeature.universal("name", "password")); + + WebTarget r = client.target(getBaseUri()).path("test/queryParamsBasic"); + assertEquals("GET 2", r.request().get(String.class)); + + r = client.target(getBaseUri()).path("test/queryParamsBasic").queryParam("param1", "value1").queryParam("param2", "value2"); + assertEquals("GET 3", r.request().get(String.class)); + + } + + @Test + public void testAuthGetQueryParamsDigest() { + ClientConfig cc = new ClientConfig(); + cc.connectorProvider(new ApacheConnectorProvider()); + Client client = ClientBuilder.newClient(cc); + client.register(HttpAuthenticationFeature.universal("name", "password")); + + WebTarget r = client.target(getBaseUri()).path("test/queryParamsDigest"); + assertEquals("GET 2", r.request().get(String.class)); + + r = client.target(getBaseUri()).path("test/queryParamsDigest").queryParam("param1", "value1").queryParam("param2", "value2"); + assertEquals("GET 3", r.request().get(String.class)); + + } } diff --git a/core-client/src/main/java/org/glassfish/jersey/client/authentication/DigestAuthenticator.java b/core-client/src/main/java/org/glassfish/jersey/client/authentication/DigestAuthenticator.java index 85741da724..b03ffa24e6 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/authentication/DigestAuthenticator.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/authentication/DigestAuthenticator.java @@ -42,6 +42,7 @@ import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; @@ -114,7 +115,7 @@ protected boolean removeEldestEntry(final Map.Entry eldest) { * @throws IOException When error with encryption occurs. */ boolean filterRequest(final ClientRequestContext request) throws IOException { - final DigestScheme digestScheme = digestCache.get(request.getUri()); + final DigestScheme digestScheme = digestCache.get(getCacheKey(request)); if (digestScheme != null) { final HttpAuthenticationFilter.Credentials cred = HttpAuthenticationFilter.getCredentials(request, this.credentials, HttpAuthenticationFilter.Type.DIGEST); @@ -155,10 +156,11 @@ public boolean filterResponse(final ClientRequestContext request, final ClientRe final boolean success = HttpAuthenticationFilter.repeatRequest(request, response, createNextAuthToken(digestScheme, request, cred)); + URI cacheKey = getCacheKey(request); if (success) { - digestCache.put(request.getUri(), digestScheme); + digestCache.put(cacheKey, digestScheme); } else { - digestCache.remove(request.getUri()); + digestCache.remove(cacheKey); } return success; } @@ -373,6 +375,24 @@ private String randomBytes(final int nbBytes) { return bytesToHex(bytes); } + private URI getCacheKey(ClientRequestContext request) { + URI requestUri = request.getUri(); + if (requestUri.getRawQuery() != null) { + // Return a URI without the query part of the request URI + try { + return new URI( + requestUri.getScheme(), + requestUri.getAuthority(), + requestUri.getPath(), + null, + requestUri.getFragment()); + } catch (URISyntaxException e) { + // Ignore and fall through + } + } + return requestUri; + } + private enum QOP { UNSPECIFIED(null), diff --git a/core-client/src/main/java/org/glassfish/jersey/client/authentication/HttpAuthenticationFilter.java b/core-client/src/main/java/org/glassfish/jersey/client/authentication/HttpAuthenticationFilter.java index 3b085f5333..64100d58ec 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/authentication/HttpAuthenticationFilter.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/authentication/HttpAuthenticationFilter.java @@ -43,15 +43,16 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.Charset; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import javax.annotation.Priority; import javax.ws.rs.Priorities; import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientResponseContext; @@ -66,8 +67,6 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; -import javax.annotation.Priority; - import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.internal.LocalizationMessages; @@ -271,7 +270,22 @@ public void filter(ClientRequestContext request, ClientResponseContext response) } private String getCacheKey(ClientRequestContext request) { - return request.getUri().toString() + ":" + request.getMethod(); + URI requestUri = request.getUri(); + if (requestUri.getRawQuery() != null) { + // Build a URI without the query part of the request URI + try { + URI requestUriWithoutQuery = new URI( + requestUri.getScheme(), + requestUri.getAuthority(), + requestUri.getPath(), + null, + requestUri.getFragment()); + return requestUriWithoutQuery.toString() + ":" + request.getMethod(); + } catch (URISyntaxException e) { + // Ignore and fall through + } + } + return requestUri.toString() + ":" + request.getMethod(); } private void updateCache(ClientRequestContext request, boolean success, Type operation) {