HADOOP-9054. Add AuthenticationHandler that uses Kerberos but allows for an alternate form of authentication for browsers. (rkanter via tucu)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1418432 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
448882534b
commit
3ff00d4aaa
|
@ -110,6 +110,7 @@
|
||||||
<exclude>**/${test.exclude}.java</exclude>
|
<exclude>**/${test.exclude}.java</exclude>
|
||||||
<exclude>${test.exclude.pattern}</exclude>
|
<exclude>${test.exclude.pattern}</exclude>
|
||||||
<exclude>**/TestKerberosAuth*.java</exclude>
|
<exclude>**/TestKerberosAuth*.java</exclude>
|
||||||
|
<exclude>**/TestAltKerberosAuth*.java</exclude>
|
||||||
<exclude>**/Test*$*.java</exclude>
|
<exclude>**/Test*$*.java</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
/**
|
||||||
|
* 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.server;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link AltKerberosAuthenticationHandler} behaves exactly the same way as
|
||||||
|
* the {@link 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;
|
||||||
|
}
|
|
@ -176,6 +176,73 @@ Configuration
|
||||||
|
|
||||||
...
|
...
|
||||||
</web-app>
|
</web-app>
|
||||||
|
+---+
|
||||||
|
|
||||||
|
** AltKerberos Configuration
|
||||||
|
|
||||||
|
<<IMPORTANT>>: A KDC must be configured and running.
|
||||||
|
|
||||||
|
The AltKerberos authentication mechanism is a partially implemented derivative
|
||||||
|
of the Kerberos SPNEGO authentication mechanism which allows a "mixed" form of
|
||||||
|
authentication where Kerberos SPNEGO is used by non-browsers while an
|
||||||
|
alternate form of authentication (to be implemented by the user) is used for
|
||||||
|
browsers. To use AltKerberos as the authentication mechanism (besides
|
||||||
|
providing an implementation), the authentication filter must be configured
|
||||||
|
with the following init parameters, in addition to the previously mentioned
|
||||||
|
Kerberos SPNEGO ones:
|
||||||
|
|
||||||
|
* <<<[PREFIX.]type>>>: the full class name of the implementation of
|
||||||
|
AltKerberosAuthenticationHandler to use.
|
||||||
|
|
||||||
|
* <<<[PREFIX.]alt-kerberos.non-browser.user-agents>>>: a comma-separated
|
||||||
|
list of which user-agents should be considered non-browsers.
|
||||||
|
|
||||||
|
<<Example>>:
|
||||||
|
|
||||||
|
+---+
|
||||||
|
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
|
||||||
|
...
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>kerberosFilter</filter-name>
|
||||||
|
<filter-class>org.apache.hadoop.security.auth.server.AuthenticationFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>type</param-name>
|
||||||
|
<param-value>org.my.subclass.of.AltKerberosAuthenticationHandler</param-value>
|
||||||
|
</init-param>
|
||||||
|
<init-param>
|
||||||
|
<param-name>alt-kerberos.non-browser.user-agents</param-name>
|
||||||
|
<param-value>java,curl,wget,perl</param-value>
|
||||||
|
</init-param>
|
||||||
|
<init-param>
|
||||||
|
<param-name>token.validity</param-name>
|
||||||
|
<param-value>30</param-value>
|
||||||
|
</init-param>
|
||||||
|
<init-param>
|
||||||
|
<param-name>cookie.domain</param-name>
|
||||||
|
<param-value>.foo.com</param-value>
|
||||||
|
</init-param>
|
||||||
|
<init-param>
|
||||||
|
<param-name>cookie.path</param-name>
|
||||||
|
<param-value>/</param-value>
|
||||||
|
</init-param>
|
||||||
|
<init-param>
|
||||||
|
<param-name>kerberos.principal</param-name>
|
||||||
|
<param-value>HTTP/localhost@LOCALHOST</param-value>
|
||||||
|
</init-param>
|
||||||
|
<init-param>
|
||||||
|
<param-name>kerberos.keytab</param-name>
|
||||||
|
<param-value>/tmp/auth.keytab</param-value>
|
||||||
|
</init-param>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>kerberosFilter</filter-name>
|
||||||
|
<url-pattern>/kerberos/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
|
||||||
|
...
|
||||||
|
</web-app>
|
||||||
+---+
|
+---+
|
||||||
|
|
||||||
\[ {{{./index.html}Go Back}} \]
|
\[ {{{./index.html}Go Back}} \]
|
||||||
|
|
|
@ -24,6 +24,11 @@ Hadoop Auth, Java HTTP SPNEGO ${project.version}
|
||||||
Hadoop Auth also supports additional authentication mechanisms on the client
|
Hadoop Auth also supports additional authentication mechanisms on the client
|
||||||
and the server side via 2 simple interfaces.
|
and the server side via 2 simple interfaces.
|
||||||
|
|
||||||
|
Additionally, it provides a partially implemented derivative of the Kerberos
|
||||||
|
SPNEGO authentication to allow a "mixed" form of authentication where Kerberos
|
||||||
|
SPNEGO is used by non-browsers while an alternate form of authentication
|
||||||
|
(to be implemented by the user) is used for browsers.
|
||||||
|
|
||||||
* License
|
* License
|
||||||
|
|
||||||
Hadoop Auth is distributed under {{{http://www.apache.org/licenses/}Apache
|
Hadoop Auth is distributed under {{{http://www.apache.org/licenses/}Apache
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/**
|
||||||
|
* 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.server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.apache.hadoop.security.authentication.client.AuthenticationException;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
public class TestAltKerberosAuthenticationHandler
|
||||||
|
extends TestKerberosAuthenticationHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected KerberosAuthenticationHandler getNewAuthenticationHandler() {
|
||||||
|
// AltKerberosAuthenticationHandler is abstract; a subclass would normally
|
||||||
|
// perform some other authentication when alternateAuthenticate() is called.
|
||||||
|
// For the test, we'll just return an AuthenticationToken as the other
|
||||||
|
// authentication is left up to the developer of the subclass
|
||||||
|
return new AltKerberosAuthenticationHandler() {
|
||||||
|
@Override
|
||||||
|
public AuthenticationToken alternateAuthenticate(
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response)
|
||||||
|
throws IOException, AuthenticationException {
|
||||||
|
return new AuthenticationToken("A", "B", getType());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getExpectedType() {
|
||||||
|
return AltKerberosAuthenticationHandler.TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAlternateAuthenticationAsBrowser() throws Exception {
|
||||||
|
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||||
|
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
|
||||||
|
|
||||||
|
// By default, a User-Agent without "java", "curl", "wget", or "perl" in it
|
||||||
|
// is considered a browser
|
||||||
|
Mockito.when(request.getHeader("User-Agent")).thenReturn("Some Browser");
|
||||||
|
|
||||||
|
AuthenticationToken token = handler.authenticate(request, response);
|
||||||
|
assertEquals("A", token.getUserName());
|
||||||
|
assertEquals("B", token.getName());
|
||||||
|
assertEquals(getExpectedType(), token.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNonDefaultNonBrowserUserAgentAsBrowser() throws Exception {
|
||||||
|
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||||
|
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
|
||||||
|
|
||||||
|
if (handler != null) {
|
||||||
|
handler.destroy();
|
||||||
|
handler = null;
|
||||||
|
}
|
||||||
|
handler = getNewAuthenticationHandler();
|
||||||
|
Properties props = getDefaultProperties();
|
||||||
|
props.setProperty("alt-kerberos.non-browser.user-agents", "foo, bar");
|
||||||
|
try {
|
||||||
|
handler.init(props);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
handler = null;
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretend we're something that will not match with "foo" (or "bar")
|
||||||
|
Mockito.when(request.getHeader("User-Agent")).thenReturn("blah");
|
||||||
|
// Should use alt authentication
|
||||||
|
AuthenticationToken token = handler.authenticate(request, response);
|
||||||
|
assertEquals("A", token.getUserName());
|
||||||
|
assertEquals("B", token.getName());
|
||||||
|
assertEquals(getExpectedType(), token.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNonDefaultNonBrowserUserAgentAsNonBrowser() throws Exception {
|
||||||
|
if (handler != null) {
|
||||||
|
handler.destroy();
|
||||||
|
handler = null;
|
||||||
|
}
|
||||||
|
handler = getNewAuthenticationHandler();
|
||||||
|
Properties props = getDefaultProperties();
|
||||||
|
props.setProperty("alt-kerberos.non-browser.user-agents", "foo, bar");
|
||||||
|
try {
|
||||||
|
handler.init(props);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
handler = null;
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the kerberos tests again
|
||||||
|
testRequestWithoutAuthorization();
|
||||||
|
testRequestWithInvalidAuthorization();
|
||||||
|
testRequestWithAuthorization();
|
||||||
|
testRequestWithInvalidKerberosAuthorization();
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,23 +28,37 @@ import org.ietf.jgss.Oid;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class TestKerberosAuthenticationHandler extends TestCase {
|
public class TestKerberosAuthenticationHandler extends TestCase {
|
||||||
|
|
||||||
private KerberosAuthenticationHandler handler;
|
protected KerberosAuthenticationHandler handler;
|
||||||
|
|
||||||
|
protected KerberosAuthenticationHandler getNewAuthenticationHandler() {
|
||||||
|
return new KerberosAuthenticationHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getExpectedType() {
|
||||||
|
return KerberosAuthenticationHandler.TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Properties getDefaultProperties() {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.setProperty(KerberosAuthenticationHandler.PRINCIPAL,
|
||||||
|
KerberosTestUtils.getServerPrincipal());
|
||||||
|
props.setProperty(KerberosAuthenticationHandler.KEYTAB,
|
||||||
|
KerberosTestUtils.getKeytabFile());
|
||||||
|
props.setProperty(KerberosAuthenticationHandler.NAME_RULES,
|
||||||
|
"RULE:[1:$1@$0](.*@" + KerberosTestUtils.getRealm()+")s/@.*//\n");
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
handler = new KerberosAuthenticationHandler();
|
handler = getNewAuthenticationHandler();
|
||||||
Properties props = new Properties();
|
Properties props = getDefaultProperties();
|
||||||
props.setProperty(KerberosAuthenticationHandler.PRINCIPAL, KerberosTestUtils.getServerPrincipal());
|
|
||||||
props.setProperty(KerberosAuthenticationHandler.KEYTAB, KerberosTestUtils.getKeytabFile());
|
|
||||||
props.setProperty(KerberosAuthenticationHandler.NAME_RULES,
|
|
||||||
"RULE:[1:$1@$0](.*@" + KerberosTestUtils.getRealm()+")s/@.*//\n");
|
|
||||||
try {
|
try {
|
||||||
handler.init(props);
|
handler.init(props);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -71,10 +85,8 @@ public class TestKerberosAuthenticationHandler extends TestCase {
|
||||||
|
|
||||||
KerberosName.setRules("RULE:[1:$1@$0](.*@FOO)s/@.*//\nDEFAULT");
|
KerberosName.setRules("RULE:[1:$1@$0](.*@FOO)s/@.*//\nDEFAULT");
|
||||||
|
|
||||||
handler = new KerberosAuthenticationHandler();
|
handler = getNewAuthenticationHandler();
|
||||||
Properties props = new Properties();
|
Properties props = getDefaultProperties();
|
||||||
props.setProperty(KerberosAuthenticationHandler.PRINCIPAL, KerberosTestUtils.getServerPrincipal());
|
|
||||||
props.setProperty(KerberosAuthenticationHandler.KEYTAB, KerberosTestUtils.getKeytabFile());
|
|
||||||
props.setProperty(KerberosAuthenticationHandler.NAME_RULES, "RULE:[1:$1@$0](.*@BAR)s/@.*//\nDEFAULT");
|
props.setProperty(KerberosAuthenticationHandler.NAME_RULES, "RULE:[1:$1@$0](.*@BAR)s/@.*//\nDEFAULT");
|
||||||
try {
|
try {
|
||||||
handler.init(props);
|
handler.init(props);
|
||||||
|
@ -97,8 +109,7 @@ public class TestKerberosAuthenticationHandler extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testType() throws Exception {
|
public void testType() throws Exception {
|
||||||
KerberosAuthenticationHandler handler = new KerberosAuthenticationHandler();
|
assertEquals(getExpectedType(), handler.getType());
|
||||||
assertEquals(KerberosAuthenticationHandler.TYPE, handler.getType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRequestWithoutAuthorization() throws Exception {
|
public void testRequestWithoutAuthorization() throws Exception {
|
||||||
|
@ -182,7 +193,7 @@ public class TestKerberosAuthenticationHandler extends TestCase {
|
||||||
|
|
||||||
assertEquals(KerberosTestUtils.getClientPrincipal(), authToken.getName());
|
assertEquals(KerberosTestUtils.getClientPrincipal(), authToken.getName());
|
||||||
assertTrue(KerberosTestUtils.getClientPrincipal().startsWith(authToken.getUserName()));
|
assertTrue(KerberosTestUtils.getClientPrincipal().startsWith(authToken.getUserName()));
|
||||||
assertEquals(KerberosAuthenticationHandler.TYPE, authToken.getType());
|
assertEquals(getExpectedType(), authToken.getType());
|
||||||
} else {
|
} else {
|
||||||
Mockito.verify(response).setHeader(Mockito.eq(KerberosAuthenticator.WWW_AUTHENTICATE),
|
Mockito.verify(response).setHeader(Mockito.eq(KerberosAuthenticator.WWW_AUTHENTICATE),
|
||||||
Mockito.matches(KerberosAuthenticator.NEGOTIATE + " .*"));
|
Mockito.matches(KerberosAuthenticator.NEGOTIATE + " .*"));
|
||||||
|
|
|
@ -14,6 +14,8 @@ Release 2.0.3-alpha - Unreleased
|
||||||
HADOOP-9090. Support on-demand publish of metrics. (Mostafa Elhemali via
|
HADOOP-9090. Support on-demand publish of metrics. (Mostafa Elhemali via
|
||||||
suresh)
|
suresh)
|
||||||
|
|
||||||
|
HADOOP-9054. Add AuthenticationHandler that uses Kerberos but allows for
|
||||||
|
an alternate form of authentication for browsers. (rkanter via tucu)
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue