Merge branch 'jetty-9.3.x' of github.com:eclipse/jetty.project into jetty-9.3.x

This commit is contained in:
Joakim Erdfelt 2016-03-02 16:48:15 -07:00
commit 8f8fcd1b1a
5 changed files with 108 additions and 21 deletions

View File

@ -40,7 +40,6 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
public static final int DEFAULT_MAX_CONTENT_LENGTH = 16*1024;
public static final Logger LOG = Log.getLogger(AuthenticationProtocolHandler.class);
private static final Pattern AUTHENTICATE_PATTERN = Pattern.compile("([^\\s]+)\\s+realm=\"([^\"]+)\"(.*)", Pattern.CASE_INSENSITIVE);
private static final String AUTHENTICATION_ATTRIBUTE = AuthenticationProtocolHandler.class.getName() + ".authentication";
private final HttpClient client;
private final int maxContentLength;
@ -64,6 +63,8 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
protected abstract URI getAuthenticationURI(Request request);
protected abstract String getAuthenticationAttribute();
@Override
public Response.Listener getResponseListener()
{
@ -92,8 +93,9 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
return;
}
String authenticationAttribute = getAuthenticationAttribute();
HttpConversation conversation = request.getConversation();
if (conversation.getAttribute(AUTHENTICATION_ATTRIBUTE) != null)
if (conversation.getAttribute(authenticationAttribute) != null)
{
// We have already tried to authenticate, but we failed again
if (LOG.isDebugEnabled())
@ -146,18 +148,12 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
return;
}
conversation.setAttribute(AUTHENTICATION_ATTRIBUTE, true);
conversation.setAttribute(authenticationAttribute, true);
Request newRequest = client.copyRequest(request, request.getURI());
authnResult.apply(newRequest);
newRequest.onResponseSuccess(new Response.SuccessListener()
{
@Override
public void onSuccess(Response response)
{
client.getAuthenticationStore().addAuthenticationResult(authnResult);
}
}).send(null);
newRequest.onResponseSuccess(r -> client.getAuthenticationStore().addAuthenticationResult(authnResult))
.send(null);
}
catch (Throwable x)
{

View File

@ -153,14 +153,9 @@ public abstract class HttpConnection implements Connection
request.header(HttpHeader.COOKIE.asString(), cookies.toString());
}
// Authorization
URI authenticationURI = proxy != null ? proxy.getURI() : request.getURI();
if (authenticationURI != null)
{
Authentication.Result authnResult = getHttpClient().getAuthenticationStore().findAuthenticationResult(authenticationURI);
if (authnResult != null)
authnResult.apply(request);
}
// Authentication
applyAuthentication(request, proxy != null ? proxy.getURI() : null);
applyAuthentication(request, request.getURI());
}
private StringBuilder convertCookies(List<HttpCookie> cookies, StringBuilder builder)
@ -177,6 +172,16 @@ public abstract class HttpConnection implements Connection
return builder;
}
private void applyAuthentication(Request request, URI uri)
{
if (uri != null)
{
Authentication.Result result = getHttpClient().getAuthenticationStore().findAuthenticationResult(uri);
if (result != null)
result.apply(request);
}
}
protected SendFailure send(HttpChannel channel, HttpExchange exchange)
{
// Forbid idle timeouts for the time window where

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.http.HttpStatus;
public class ProxyAuthenticationProtocolHandler extends AuthenticationProtocolHandler
{
public static final String NAME = "proxy-authenticate";
private static final String ATTRIBUTE = ProxyAuthenticationProtocolHandler.class.getName() + ".attribute";
public ProxyAuthenticationProtocolHandler(HttpClient client)
{
@ -76,4 +77,10 @@ public class ProxyAuthenticationProtocolHandler extends AuthenticationProtocolHa
ProxyConfiguration.Proxy proxy = destination.getProxy();
return proxy != null ? proxy.getURI() : request.getURI();
}
@Override
protected String getAuthenticationAttribute()
{
return ATTRIBUTE;
}
}

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.http.HttpStatus;
public class WWWAuthenticationProtocolHandler extends AuthenticationProtocolHandler
{
public static final String NAME = "www-authenticate";
private static final String ATTRIBUTE = WWWAuthenticationProtocolHandler.class.getName() + ".attribute";
public WWWAuthenticationProtocolHandler(HttpClient client)
{
@ -74,4 +75,10 @@ public class WWWAuthenticationProtocolHandler extends AuthenticationProtocolHand
{
return request.getURI();
}
@Override
protected String getAuthenticationAttribute()
{
return ATTRIBUTE;
}
}

View File

@ -81,7 +81,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
}
@Test
public void testAuthenticatedProxiedRequest() throws Exception
public void testProxyAuthentication() throws Exception
{
final String user = "foo";
final String password = "bar";
@ -160,7 +160,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
}
@Test
public void testAuthenticatedProxiedRequestWithRedirect() throws Exception
public void testProxyAuthenticationWithRedirect() throws Exception
{
String user = "foo";
String password = "bar";
@ -254,4 +254,76 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
Assert.assertEquals(status, response3.getStatus());
Assert.assertEquals(1, requests.get());
}
@Test
public void testProxyAuthenticationWithServerAuthentication() throws Exception
{
String proxyRealm = "proxyRealm";
String serverRealm = "serverRealm";
int status = HttpStatus.NO_CONTENT_204;
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
String authorization = request.getHeader(HttpHeader.PROXY_AUTHORIZATION.asString());
if (authorization == null)
{
response.setStatus(HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407);
response.setHeader(HttpHeader.PROXY_AUTHENTICATE.asString(), "Basic realm=\"" + proxyRealm + "\"");
}
else
{
authorization = request.getHeader(HttpHeader.AUTHORIZATION.asString());
if (authorization == null)
{
response.setStatus(HttpStatus.UNAUTHORIZED_401);
response.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), "Basic realm=\"" + serverRealm + "\"");
}
else
{
response.setStatus(status);
}
}
}
});
String proxyHost = "localhost";
int proxyPort = connector.getLocalPort();
String serverHost = "server";
int serverPort = proxyPort + 1;
URI proxyURI = URI.create(scheme + "://" + proxyHost + ":" + proxyPort);
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword"));
URI serverURI = URI.create(scheme + "://" + serverHost + ":" + serverPort);
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(serverURI, serverRealm, "serverUser", "serverPassword"));
client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort));
final AtomicInteger requests = new AtomicInteger();
client.getRequestListeners().add(new Request.Listener.Adapter()
{
@Override
public void onSuccess(Request request)
{
requests.incrementAndGet();
}
});
// Make a request, expect 407 + 401 + 204.
ContentResponse response1 = client.newRequest(serverHost, serverPort)
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(status, response1.getStatus());
Assert.assertEquals(3, requests.get());
// Make again the request, authentication is cached, expect 204.
requests.set(0);
ContentResponse response2 = client.newRequest(serverHost, serverPort)
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(status, response2.getStatus());
Assert.assertEquals(1, requests.get());
}
}