All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.security.authentication.client.AuthenticatedURL Maven / Gradle / Ivy

There is a newer version: 3.2.0-9
Show newest version
/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. See accompanying LICENSE file.
 */
package org.apache.hadoop.security.authentication.client;

import org.apache.hadoop.security.authentication.server.AuthenticationFilter;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * The {@link AuthenticatedURL} class enables the use of the JDK {@link URL} class
 * against HTTP endpoints protected with the {@link AuthenticationFilter}.
 * 

* The authentication mechanisms supported by default are Hadoop Simple authentication * (also known as pseudo authentication) and Kerberos SPNEGO authentication. *

* Additional authentication mechanisms can be supported via {@link Authenticator} implementations. *

* The default {@link Authenticator} is the {@link KerberosAuthenticator} class which supports * automatic fallback from Kerberos SPNEGO to Hadoop Simple authentication. *

* AuthenticatedURL instances are not thread-safe. *

* The usage pattern of the {@link AuthenticatedURL} is: *

 *
 * // establishing an initial connection
 *
 * URL url = new URL("http://foo:8080/bar");
 * AuthenticatedURL.Token token = new AuthenticatedURL.Token();
 * AuthenticatedURL aUrl = new AuthenticatedURL();
 * HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection();
 * ....
 * // use the 'conn' instance
 * ....
 *
 * // establishing a follow up connection using a token from the previous connection
 *
 * HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection();
 * ....
 * // use the 'conn' instance
 * ....
 *
 * 
*/ public class AuthenticatedURL { /** * Name of the HTTP cookie used for the authentication token between the client and the server. */ public static final String AUTH_COOKIE = "hadoop.auth"; private static final String AUTH_COOKIE_EQ = AUTH_COOKIE + "="; /** * Client side authentication token. */ public static class Token { private String token; /** * Creates a token. */ public Token() { } /** * Creates a token using an existing string representation of the token. * * @param tokenStr string representation of the tokenStr. */ public Token(String tokenStr) { if (tokenStr == null) { throw new IllegalArgumentException("tokenStr cannot be null"); } set(tokenStr); } /** * Returns if a token from the server has been set. * * @return if a token from the server has been set. */ public boolean isSet() { return token != null; } /** * Sets a token. * * @param tokenStr string representation of the tokenStr. */ void set(String tokenStr) { token = tokenStr; } /** * Returns the string representation of the token. * * @return the string representation of the token. */ @Override public String toString() { return token; } } private static Class DEFAULT_AUTHENTICATOR = KerberosAuthenticator.class; /** * Sets the default {@link Authenticator} class to use when an {@link AuthenticatedURL} instance * is created without specifying an authenticator. * * @param authenticator the authenticator class to use as default. */ public static void setDefaultAuthenticator(Class authenticator) { DEFAULT_AUTHENTICATOR = authenticator; } /** * Returns the default {@link Authenticator} class to use when an {@link AuthenticatedURL} instance * is created without specifying an authenticator. * * @return the authenticator class to use as default. */ public static Class getDefaultAuthenticator() { return DEFAULT_AUTHENTICATOR; } private Authenticator authenticator; private ConnectionConfigurator connConfigurator; /** * Creates an {@link AuthenticatedURL}. */ public AuthenticatedURL() { this(null); } /** * Creates an AuthenticatedURL. * * @param authenticator the {@link Authenticator} instance to use, if null a {@link * KerberosAuthenticator} is used. */ public AuthenticatedURL(Authenticator authenticator) { this(authenticator, null); } /** * Creates an AuthenticatedURL. * * @param authenticator the {@link Authenticator} instance to use, if null a {@link * KerberosAuthenticator} is used. * @param connConfigurator a connection configurator. */ public AuthenticatedURL(Authenticator authenticator, ConnectionConfigurator connConfigurator) { try { this.authenticator = (authenticator != null) ? authenticator : DEFAULT_AUTHENTICATOR.newInstance(); } catch (Exception ex) { throw new RuntimeException(ex); } this.connConfigurator = connConfigurator; this.authenticator.setConnectionConfigurator(connConfigurator); } /** * Returns the {@link Authenticator} instance used by the * AuthenticatedURL. * * @return the {@link Authenticator} instance */ protected Authenticator getAuthenticator() { return authenticator; } /** * Returns an authenticated {@link HttpURLConnection}. * * @param url the URL to connect to. Only HTTP/S URLs are supported. * @param token the authentication token being used for the user. * * @return an authenticated {@link HttpURLConnection}. * * @throws IOException if an IO error occurred. * @throws AuthenticationException if an authentication exception occurred. */ public HttpURLConnection openConnection(URL url, Token token) throws IOException, AuthenticationException { if (url == null) { throw new IllegalArgumentException("url cannot be NULL"); } if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) { throw new IllegalArgumentException("url must be for a HTTP or HTTPS resource"); } if (token == null) { throw new IllegalArgumentException("token cannot be NULL"); } authenticator.authenticate(url, token); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); if (connConfigurator != null) { conn = connConfigurator.configure(conn); } injectToken(conn, token); return conn; } /** * Helper method that injects an authentication token to send with a connection. * * @param conn connection to inject the authentication token into. * @param token authentication token to inject. */ public static void injectToken(HttpURLConnection conn, Token token) { String t = token.token; if (t != null) { if (!t.startsWith("\"")) { t = "\"" + t + "\""; } conn.addRequestProperty("Cookie", AUTH_COOKIE_EQ + t); } } /** * Helper method that extracts an authentication token received from a connection. *

* This method is used by {@link Authenticator} implementations. * * @param conn connection to extract the authentication token from. * @param token the authentication token. * * @throws IOException if an IO error occurred. * @throws AuthenticationException if an authentication exception occurred. */ public static void extractToken(HttpURLConnection conn, Token token) throws IOException, AuthenticationException { int respCode = conn.getResponseCode(); if (respCode == HttpURLConnection.HTTP_OK || respCode == HttpURLConnection.HTTP_CREATED || respCode == HttpURLConnection.HTTP_ACCEPTED) { Map> headers = conn.getHeaderFields(); List cookies = headers.get("Set-Cookie"); if (cookies != null) { for (String cookie : cookies) { if (cookie.startsWith(AUTH_COOKIE_EQ)) { String value = cookie.substring(AUTH_COOKIE_EQ.length()); int separator = value.indexOf(";"); if (separator > -1) { value = value.substring(0, separator); } if (value.length() > 0) { token.set(value); } } } } } else { token.set(null); throw new AuthenticationException("Authentication failed, status: " + conn.getResponseCode() + ", message: " + conn.getResponseMessage()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy