forked from vmware/LittleProxy
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ProxyAuthenticator enhancements (adamfisk#8)
* Changed ProxyAuthenticator to be more generic. It accepts AuthorizationHeader and HttpRequest * Refactored a bit
- Loading branch information
Showing
6 changed files
with
130 additions
and
66 deletions.
There are no files selected for viewing
40 changes: 40 additions & 0 deletions
40
src/main/java/org/littleshoot/proxy/AbstractProxyAuthenticator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package org.littleshoot.proxy; | ||
|
||
import org.littleshoot.proxy.impl.ProxyUtils; | ||
|
||
import java.util.Date; | ||
|
||
import io.netty.handler.codec.http.FullHttpResponse; | ||
import io.netty.handler.codec.http.HttpHeaders; | ||
import io.netty.handler.codec.http.HttpRequest; | ||
import io.netty.handler.codec.http.HttpResponseStatus; | ||
import io.netty.handler.codec.http.HttpVersion; | ||
|
||
public abstract class AbstractProxyAuthenticator implements ProxyAuthenticator { | ||
|
||
@Override | ||
public abstract boolean authenticate(HttpRequest request); | ||
|
||
@Override | ||
public abstract String getRealm(); | ||
|
||
@Override | ||
public FullHttpResponse authenticationFailureResponse(HttpRequest request) { | ||
String body = "<!DOCTYPE HTML \"-//IETF//DTD HTML 2.0//EN\">\n" | ||
+ "<html><head>\n" | ||
+ "<title>407 Proxy Authentication Required</title>\n" | ||
+ "</head><body>\n" | ||
+ "<h1>Proxy Authentication Required</h1>\n" | ||
+ "<p>This server could not verify that you\n" | ||
+ "are authorized to access the document\n" | ||
+ "requested. Either you supplied the wrong\n" | ||
+ "credentials (e.g., bad password), or your\n" | ||
+ "browser doesn't understand how to supply\n" | ||
+ "the credentials required.</p>\n" + "</body></html>\n"; | ||
FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, | ||
HttpResponseStatus.PROXY_AUTHENTICATION_REQUIRED, body); | ||
HttpHeaders.setDate(response, new Date()); | ||
response.headers().set("Proxy-Authenticate", "Basic realm=\"" + (getRealm() == null ? "Restricted Files" : getRealm()) + "\""); | ||
return response; | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
src/main/java/org/littleshoot/proxy/BasicProxyAuthenticator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package org.littleshoot.proxy; | ||
|
||
import com.google.common.io.BaseEncoding; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.nio.charset.Charset; | ||
import java.util.List; | ||
|
||
import io.netty.handler.codec.http.HttpHeaders; | ||
import io.netty.handler.codec.http.HttpRequest; | ||
|
||
/** | ||
* Basic Auth user/password authenticator | ||
*/ | ||
public abstract class BasicProxyAuthenticator extends AbstractProxyAuthenticator { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(BasicProxyAuthenticator.class); | ||
|
||
@Override | ||
public boolean authenticate(HttpRequest request) { | ||
if (!request.headers().contains(HttpHeaders.Names.PROXY_AUTHORIZATION)) { | ||
return false; | ||
} | ||
|
||
List<String> values = request.headers().getAll(HttpHeaders.Names.PROXY_AUTHORIZATION); | ||
String fullValue = values.iterator().next(); | ||
String value = StringUtils.substringAfter(fullValue, "Basic ").trim(); | ||
|
||
if (StringUtils.isNotEmpty(value)) { | ||
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 authenticate(userName, password, request); | ||
} | ||
|
||
LOG.debug("Invalid authentication scheme. Expected 'Basic'"); | ||
return false; | ||
} | ||
|
||
public abstract boolean authenticate(String username, String password, HttpRequest request); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 20 additions & 13 deletions
33
src/test/java/org/littleshoot/proxy/UsernamePasswordAuthenticatingProxyTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,47 @@ | ||
package org.littleshoot.proxy; | ||
|
||
import io.netty.handler.codec.http.HttpRequest; | ||
|
||
/** | ||
* Tests a single proxy that requires username/password authentication. | ||
*/ | ||
public class UsernamePasswordAuthenticatingProxyTest extends BaseProxyTest | ||
implements ProxyAuthenticator { | ||
public class UsernamePasswordAuthenticatingProxyTest extends BaseProxyTest { | ||
private static String USERNAME = "user1"; | ||
private static String PASSWORD = "password"; | ||
|
||
@Override | ||
protected void setUp() { | ||
this.proxyServer = bootstrapProxy() | ||
.withPort(0) | ||
.withProxyAuthenticator(this) | ||
.withProxyAuthenticator(new TestBasicProxyAuthenticator()) | ||
.start(); | ||
} | ||
|
||
@Override | ||
protected String getUsername() { | ||
return "user1"; | ||
return USERNAME; | ||
} | ||
|
||
@Override | ||
protected String getPassword() { | ||
return "user2"; | ||
} | ||
|
||
@Override | ||
public boolean authenticate(String userName, String password) { | ||
return getUsername().equals(userName) && getPassword().equals(password); | ||
return PASSWORD; | ||
} | ||
|
||
@Override | ||
protected boolean isAuthenticating() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public String getRealm() { | ||
return null; | ||
static class TestBasicProxyAuthenticator extends BasicProxyAuthenticator { | ||
|
||
@Override | ||
public String getRealm() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public boolean authenticate(String username, String password, HttpRequest request) { | ||
return USERNAME.equals(username) && PASSWORD.equals(password); | ||
} | ||
} | ||
} |