From de9e01c05bd00f2ef9d3cb9447f215ec70f10729 Mon Sep 17 00:00:00 2001 From: Marshall Jones Date: Mon, 6 Mar 2017 10:21:42 -0800 Subject: [PATCH 1/2] Allow passing the authorization headers --- .../proxy/BasicProxyAuthenticator.java | 33 +++++++++++++++++++ .../littleshoot/proxy/ProxyAuthenticator.java | 14 ++++++++ .../proxy/impl/ClientToProxyConnection.java | 10 +----- ...ernamePasswordAuthenticatingProxyTest.java | 1 + ...ernamePasswordAuthenticatingProxyTest.java | 5 +++ 5 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java diff --git a/src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java b/src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java new file mode 100644 index 000000000..97f81d38a --- /dev/null +++ b/src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java @@ -0,0 +1,33 @@ +package org.littleshoot.proxy; + +import com.google.common.io.BaseEncoding; + +import org.apache.commons.lang3.StringUtils; + +import java.nio.charset.Charset; + +/** + * + */ +public class BasicProxyAuthenticator { + + private final ProxyAuthenticator proxyAuthenticator; + + public BasicProxyAuthenticator(ProxyAuthenticator proxyAuthenticator) { + this.proxyAuthenticator = proxyAuthenticator; + } + + public boolean authenticate(String proxyAuthorizationHeaderValue) { + String value = StringUtils.substringAfter(proxyAuthorizationHeaderValue, "Basic ").trim(); + + byte[] decodedValue = BaseEncoding.base64().decode(value); + + String decodedString = new String(decodedValue, Charset.forName("UTF-8")); + + String userName = StringUtils.substringBefore(decodedString, ":"); + String password = StringUtils.substringAfter(decodedString, ":"); + + return proxyAuthenticator.authenticate(userName, password); + } + +} diff --git a/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java b/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java index df77c687f..f7fa671bb 100644 --- a/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java +++ b/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java @@ -5,6 +5,17 @@ * the basis of a username and password. */ public interface ProxyAuthenticator { + + /** + * Authenticates the user using the specified proxy authorization header. + * + * @param proxyAuthorizationHeaderValue + * The proxy authorization header value. + * @return true if the credential is acceptable, otherwise + * false. + */ + boolean authenticate(String proxyAuthorizationHeaderValue); + /** * Authenticates the user using the specified userName and password. * @@ -14,7 +25,10 @@ public interface ProxyAuthenticator { * The password. * @return true if the credentials are acceptable, otherwise * false. + * @deprecated Use BasicProxyAuthenticator.authenticate to authenticate Basic authorization + * requests. */ + @Deprecated boolean authenticate(String userName, String password); /** diff --git a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java index 964858fbf..f7c906c71 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java @@ -982,15 +982,7 @@ private boolean authenticationRequired(HttpRequest request) { List values = request.headers().getAll( HttpHeaders.Names.PROXY_AUTHORIZATION); String fullValue = values.iterator().next(); - String value = StringUtils.substringAfter(fullValue, "Basic ").trim(); - - byte[] decodedValue = BaseEncoding.base64().decode(value); - - String decodedString = new String(decodedValue, Charset.forName("UTF-8")); - - String userName = StringUtils.substringBefore(decodedString, ":"); - String password = StringUtils.substringAfter(decodedString, ":"); - if (!authenticator.authenticate(userName, password)) { + if (!authenticator.authenticate(fullValue)) { writeAuthenticationRequired(authenticator.getRealm()); return true; } diff --git a/src/test/java/org/littleshoot/proxy/MITMUsernamePasswordAuthenticatingProxyTest.java b/src/test/java/org/littleshoot/proxy/MITMUsernamePasswordAuthenticatingProxyTest.java index 48369cdd0..f9ef07210 100644 --- a/src/test/java/org/littleshoot/proxy/MITMUsernamePasswordAuthenticatingProxyTest.java +++ b/src/test/java/org/littleshoot/proxy/MITMUsernamePasswordAuthenticatingProxyTest.java @@ -22,4 +22,5 @@ protected void setUp() { protected boolean isMITM() { return true; } + } diff --git a/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java b/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java index f3c704aeb..e46fe1d82 100644 --- a/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java +++ b/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java @@ -23,6 +23,11 @@ protected String getPassword() { return "user2"; } + @Override + public boolean authenticate(String proxyAuthorizationHeaderValue) { + return new BasicProxyAuthenticator(this).authenticate(proxyAuthorizationHeaderValue); + } + @Override public boolean authenticate(String userName, String password) { return getUsername().equals(userName) && getPassword().equals(password); From 08ef627d15abc38f2c3ba918acc51db60ea84d45 Mon Sep 17 00:00:00 2001 From: Marshall Jones Date: Mon, 6 Mar 2017 15:35:32 -0800 Subject: [PATCH 2/2] Better implementation --- .../proxy/BasicProxyAuthenticator.java | 25 +++++++++++------ .../littleshoot/proxy/ProxyAuthenticator.java | 15 ---------- ...ernamePasswordAuthenticatingProxyTest.java | 28 +++++++++++++++---- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java b/src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java index 97f81d38a..6d69c4598 100644 --- a/src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java +++ b/src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java @@ -9,14 +9,9 @@ /** * */ -public class BasicProxyAuthenticator { - - private final ProxyAuthenticator proxyAuthenticator; - - public BasicProxyAuthenticator(ProxyAuthenticator proxyAuthenticator) { - this.proxyAuthenticator = proxyAuthenticator; - } +public abstract class BasicProxyAuthenticator implements ProxyAuthenticator { + @Override public boolean authenticate(String proxyAuthorizationHeaderValue) { String value = StringUtils.substringAfter(proxyAuthorizationHeaderValue, "Basic ").trim(); @@ -27,7 +22,21 @@ public boolean authenticate(String proxyAuthorizationHeaderValue) { String userName = StringUtils.substringBefore(decodedString, ":"); String password = StringUtils.substringAfter(decodedString, ":"); - return proxyAuthenticator.authenticate(userName, password); + return authenticate(userName, password); } + /** + * Authenticates the user using the specified userName and password. + * + * @param username + * The user name. + * @param password + * The password. + * @return true if the credentials are acceptable, otherwise + * false. + * requests. + */ + abstract boolean authenticate(String username, String password); + + abstract public String getRealm(); } diff --git a/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java b/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java index f7fa671bb..493d4f476 100644 --- a/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java +++ b/src/main/java/org/littleshoot/proxy/ProxyAuthenticator.java @@ -16,21 +16,6 @@ public interface ProxyAuthenticator { */ boolean authenticate(String proxyAuthorizationHeaderValue); - /** - * Authenticates the user using the specified userName and password. - * - * @param userName - * The user name. - * @param password - * The password. - * @return true if the credentials are acceptable, otherwise - * false. - * @deprecated Use BasicProxyAuthenticator.authenticate to authenticate Basic authorization - * requests. - */ - @Deprecated - boolean authenticate(String userName, String password); - /** * The realm value to be used in the request for proxy authentication * ("Proxy-Authenticate" header). Returning null will cause the string diff --git a/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java b/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java index e46fe1d82..511fb26a6 100644 --- a/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java +++ b/src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java @@ -25,12 +25,7 @@ protected String getPassword() { @Override public boolean authenticate(String proxyAuthorizationHeaderValue) { - return new BasicProxyAuthenticator(this).authenticate(proxyAuthorizationHeaderValue); - } - - @Override - public boolean authenticate(String userName, String password) { - return getUsername().equals(userName) && getPassword().equals(password); + return new TestBasicProxyAuthenticator(getUsername(), getPassword()).authenticate(proxyAuthorizationHeaderValue); } @Override @@ -42,4 +37,25 @@ protected boolean isAuthenticating() { public String getRealm() { return null; } + + static class TestBasicProxyAuthenticator extends BasicProxyAuthenticator{ + + private final String username; + private final String password; + + TestBasicProxyAuthenticator(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + boolean authenticate(String username, String password) { + return this.username.equals(username) && this.password.equals(password); + } + + @Override + public String getRealm() { + return null; + } + } }