Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.oozie.authentication; import java.io.IOException; import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.server.AuthenticationToken; import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler; // TODO: Delete this class when hadoop's AltKerberosAuthenticationHandler becomes available in a hadoop release /** * The {@link AltKerberosAuthenticationHandler} behaves exactly the same way as the KerberosAuthenticationHandler, except that it * allows for an alternative form of authentication for browsers while still using Kerberos for Java access. This is an abstract * class that should be subclassed to allow a developer to implement their own custom authentication for browser access. The * alternateAuthenticate method will be called whenever a request comes from a browser. * <p/> */ public abstract class AltKerberosAuthenticationHandler extends KerberosAuthenticationHandler { /** * Constant that identifies the authentication mechanism. */ public static final String TYPE = "alt-kerberos"; /** * Constant for the configuration property that indicates which user agents are not considered browsers (comma separated) */ public static final String NON_BROWSER_USER_AGENTS = TYPE + ".non-browser.user-agents"; private static final String NON_BROWSER_USER_AGENTS_DEFAULT = "java,curl,wget,perl"; private String[] nonBrowserUserAgents; /** * Returns the authentication type of the authentication handler, 'alt-kerberos'. * <p/> * * @return the authentication type of the authentication handler, 'alt-kerberos'. */ @Override public String getType() { return TYPE; } @Override public void init(Properties config) throws ServletException { super.init(config); nonBrowserUserAgents = config.getProperty(NON_BROWSER_USER_AGENTS, NON_BROWSER_USER_AGENTS_DEFAULT) .split("\\W*,\\W*"); for (int i = 0; i < nonBrowserUserAgents.length; i++) { nonBrowserUserAgents[i] = nonBrowserUserAgents[i].toLowerCase(); } } /** * It enforces the the Kerberos SPNEGO authentication sequence returning an {@link AuthenticationToken} only after the Kerberos * SPNEGO sequence has completed successfully (in the case of Java access) and only after the custom authentication implemented * by the subclass in alternateAuthenticate has completed successfully (in the case of browser access). * <p/> * * @param request the HTTP client request. * @param response the HTTP client response. * * @return an authentication token if the request is authorized or null * * @throws IOException thrown if an IO error occurred * @throws AuthenticationException thrown if an authentication error occurred */ @Override public AuthenticationToken authenticate(HttpServletRequest request, HttpServletResponse response) throws IOException, AuthenticationException { AuthenticationToken token; if (isBrowser(request.getHeader("User-Agent"))) { token = alternateAuthenticate(request, response); } else { token = super.authenticate(request, response); } return token; } /** * This method parses the User-Agent String and returns whether or not it refers to a browser. If its not a browser, then * Kerberos authentication will be used; if it is a browser, alternateAuthenticate from the subclass will be used. * <p/> * A User-Agent String is considered to be a browser if it does not contain any of the values from * alt-kerberos.non-browser.user-agents; the default behavior is to consider everything a browser unless it contains one of: * "java", "curl", "wget", or "perl". Subclasses can optionally override this method to use different behavior. * * @param userAgent The User-Agent String, or null if there isn't one * @return true if the User-Agent String refers to a browser, false if not */ protected boolean isBrowser(String userAgent) { if (userAgent == null) { return false; } userAgent = userAgent.toLowerCase(); boolean isBrowser = true; for (String nonBrowserUserAgent : nonBrowserUserAgents) { if (userAgent.contains(nonBrowserUserAgent)) { isBrowser = false; break; } } return isBrowser; } /** * Subclasses should implement this method to provide the custom authentication to be used for browsers. * * @param request the HTTP client request. * @param response the HTTP client response. * @return an authentication token if the request is authorized, or null * @throws IOException thrown if an IO error occurs * @throws AuthenticationException thrown if an authentication error occurs */ public abstract AuthenticationToken alternateAuthenticate(HttpServletRequest request, HttpServletResponse response) throws IOException, AuthenticationException; }