|
@@ -13,6 +13,8 @@
|
|
|
*/
|
|
|
package org.apache.hadoop.security.authentication.client;
|
|
|
|
|
|
+import com.google.common.annotations.VisibleForTesting;
|
|
|
+import java.lang.reflect.Constructor;
|
|
|
import org.apache.commons.codec.binary.Base64;
|
|
|
import org.apache.hadoop.security.authentication.server.HttpConstants;
|
|
|
import org.apache.hadoop.security.authentication.util.AuthToken;
|
|
@@ -177,41 +179,65 @@ public class KerberosAuthenticator implements Authenticator {
|
|
|
*/
|
|
|
@Override
|
|
|
public void authenticate(URL url, AuthenticatedURL.Token token)
|
|
|
- throws IOException, AuthenticationException {
|
|
|
+ throws IOException, AuthenticationException {
|
|
|
if (!token.isSet()) {
|
|
|
this.url = url;
|
|
|
base64 = new Base64(0);
|
|
|
- HttpURLConnection conn = token.openConnection(url, connConfigurator);
|
|
|
- conn.setRequestMethod(AUTH_HTTP_METHOD);
|
|
|
- conn.connect();
|
|
|
-
|
|
|
- boolean needFallback = false;
|
|
|
- if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
|
|
- LOG.debug("JDK performed authentication on our behalf.");
|
|
|
- // If the JDK already did the SPNEGO back-and-forth for
|
|
|
- // us, just pull out the token.
|
|
|
- AuthenticatedURL.extractToken(conn, token);
|
|
|
- if (isTokenKerberos(token)) {
|
|
|
- return;
|
|
|
+ try {
|
|
|
+ HttpURLConnection conn = token.openConnection(url, connConfigurator);
|
|
|
+ conn.setRequestMethod(AUTH_HTTP_METHOD);
|
|
|
+ conn.connect();
|
|
|
+
|
|
|
+ boolean needFallback = false;
|
|
|
+ if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
|
|
+ LOG.debug("JDK performed authentication on our behalf.");
|
|
|
+ // If the JDK already did the SPNEGO back-and-forth for
|
|
|
+ // us, just pull out the token.
|
|
|
+ AuthenticatedURL.extractToken(conn, token);
|
|
|
+ if (isTokenKerberos(token)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ needFallback = true;
|
|
|
}
|
|
|
- needFallback = true;
|
|
|
- }
|
|
|
- if (!needFallback && isNegotiate(conn)) {
|
|
|
- LOG.debug("Performing our own SPNEGO sequence.");
|
|
|
- doSpnegoSequence(token);
|
|
|
- } else {
|
|
|
- LOG.debug("Using fallback authenticator sequence.");
|
|
|
- Authenticator auth = getFallBackAuthenticator();
|
|
|
- // Make sure that the fall back authenticator have the same
|
|
|
- // ConnectionConfigurator, since the method might be overridden.
|
|
|
- // Otherwise the fall back authenticator might not have the information
|
|
|
- // to make the connection (e.g., SSL certificates)
|
|
|
- auth.setConnectionConfigurator(connConfigurator);
|
|
|
- auth.authenticate(url, token);
|
|
|
+ if (!needFallback && isNegotiate(conn)) {
|
|
|
+ LOG.debug("Performing our own SPNEGO sequence.");
|
|
|
+ doSpnegoSequence(token);
|
|
|
+ } else {
|
|
|
+ LOG.debug("Using fallback authenticator sequence.");
|
|
|
+ Authenticator auth = getFallBackAuthenticator();
|
|
|
+ // Make sure that the fall back authenticator have the same
|
|
|
+ // ConnectionConfigurator, since the method might be overridden.
|
|
|
+ // Otherwise the fall back authenticator might not have the
|
|
|
+ // information to make the connection (e.g., SSL certificates)
|
|
|
+ auth.setConnectionConfigurator(connConfigurator);
|
|
|
+ auth.authenticate(url, token);
|
|
|
+ }
|
|
|
+ } catch (IOException ex){
|
|
|
+ throw wrapExceptionWithMessage(ex,
|
|
|
+ "Error while authenticating with endpoint: " + url);
|
|
|
+ } catch (AuthenticationException ex){
|
|
|
+ throw wrapExceptionWithMessage(ex,
|
|
|
+ "Error while authenticating with endpoint: " + url);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @VisibleForTesting
|
|
|
+ static <T extends Exception> T wrapExceptionWithMessage(
|
|
|
+ T exception, String msg) {
|
|
|
+ Class<? extends Throwable> exceptionClass = exception.getClass();
|
|
|
+ try {
|
|
|
+ Constructor<? extends Throwable> ctor = exceptionClass
|
|
|
+ .getConstructor(String.class);
|
|
|
+ Throwable t = ctor.newInstance(msg);
|
|
|
+ return (T) (t.initCause(exception));
|
|
|
+ } catch (Throwable e) {
|
|
|
+ LOG.debug("Unable to wrap exception of type {}, it has "
|
|
|
+ + "no (String) constructor.", exceptionClass, e);
|
|
|
+ return exception;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* If the specified URL does not support SPNEGO authentication, a fallback {@link Authenticator} will be used.
|
|
|
* <p>
|