hadoop-12050. Enable MaxInactiveInterval for hadoop http auth token. Contributed by Huizhi Lu.
This commit is contained in:
parent
14215c8ef8
commit
71aedfabf3
@ -145,6 +145,13 @@ public class AuthenticationFilter implements Filter {
|
||||
|
||||
public static final String SIGNATURE_SECRET_FILE = SIGNATURE_SECRET + ".file";
|
||||
|
||||
/**
|
||||
* Constant for the configuration property
|
||||
* that indicates the max inactive interval of the generated token.
|
||||
*/
|
||||
public static final String
|
||||
AUTH_TOKEN_MAX_INACTIVE_INTERVAL = "token.MaxInactiveInterval";
|
||||
|
||||
/**
|
||||
* Constant for the configuration property that indicates the validity of the generated token.
|
||||
*/
|
||||
@ -190,6 +197,7 @@ public class AuthenticationFilter implements Filter {
|
||||
private Signer signer;
|
||||
private SignerSecretProvider secretProvider;
|
||||
private AuthenticationHandler authHandler;
|
||||
private long maxInactiveInterval;
|
||||
private long validity;
|
||||
private String cookieDomain;
|
||||
private String cookiePath;
|
||||
@ -227,6 +235,8 @@ public void init(FilterConfig filterConfig) throws ServletException {
|
||||
authHandlerClassName = authHandlerName;
|
||||
}
|
||||
|
||||
maxInactiveInterval = Long.parseLong(config.getProperty(
|
||||
AUTH_TOKEN_MAX_INACTIVE_INTERVAL, "1800")) * 1000; // 30 minutes;
|
||||
validity = Long.parseLong(config.getProperty(AUTH_TOKEN_VALIDITY, "36000"))
|
||||
* 1000; //10 hours
|
||||
initializeSecretProvider(filterConfig);
|
||||
@ -354,6 +364,15 @@ protected boolean isCustomSignerSecretProvider() {
|
||||
.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max inactive interval time of the generated tokens.
|
||||
*
|
||||
* @return the max inactive interval time of the generated tokens in seconds.
|
||||
*/
|
||||
protected long getMaxInactiveInterval() {
|
||||
return maxInactiveInterval / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the validity time of the generated tokens.
|
||||
*
|
||||
@ -510,8 +529,10 @@ protected AuthenticationToken getToken(HttpServletRequest request) throws IOExce
|
||||
* @throws ServletException thrown if a processing error occurred.
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
public void doFilter(ServletRequest request,
|
||||
ServletResponse response,
|
||||
FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
boolean unauthorizedResponse = true;
|
||||
int errCode = HttpServletResponse.SC_UNAUTHORIZED;
|
||||
AuthenticationException authenticationEx = null;
|
||||
@ -533,19 +554,27 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
|
||||
if (authHandler.managementOperation(token, httpRequest, httpResponse)) {
|
||||
if (token == null) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Request [{}] triggering authentication", getRequestURL(httpRequest));
|
||||
LOG.debug("Request [{}] triggering authentication",
|
||||
getRequestURL(httpRequest));
|
||||
}
|
||||
token = authHandler.authenticate(httpRequest, httpResponse);
|
||||
if (token != null && token.getExpires() != 0 &&
|
||||
token != AuthenticationToken.ANONYMOUS) {
|
||||
token.setExpires(System.currentTimeMillis() + getValidity() * 1000);
|
||||
if (token != null && token != AuthenticationToken.ANONYMOUS) {
|
||||
if (token.getMaxInactives() != 0) {
|
||||
token.setMaxInactives(System.currentTimeMillis()
|
||||
+ getMaxInactiveInterval() * 1000);
|
||||
}
|
||||
if (token.getExpires() != 0) {
|
||||
token.setExpires(System.currentTimeMillis()
|
||||
+ getValidity() * 1000);
|
||||
}
|
||||
}
|
||||
newToken = true;
|
||||
}
|
||||
if (token != null) {
|
||||
unauthorizedResponse = false;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Request [{}] user [{}] authenticated", getRequestURL(httpRequest), token.getUserName());
|
||||
LOG.debug("Request [{}] user [{}] authenticated",
|
||||
getRequestURL(httpRequest), token.getUserName());
|
||||
}
|
||||
final AuthenticationToken authToken = token;
|
||||
httpRequest = new HttpServletRequestWrapper(httpRequest) {
|
||||
@ -562,10 +591,22 @@ public String getRemoteUser() {
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return (authToken != AuthenticationToken.ANONYMOUS) ? authToken : null;
|
||||
return (authToken != AuthenticationToken.ANONYMOUS) ?
|
||||
authToken : null;
|
||||
}
|
||||
};
|
||||
if (newToken && !token.isExpired() && token != AuthenticationToken.ANONYMOUS) {
|
||||
|
||||
// If cookie persistence is configured to false,
|
||||
// it means the cookie will be a session cookie.
|
||||
// If the token is an old one, renew the its maxInactiveInterval.
|
||||
if (!newToken && !isCookiePersistent()
|
||||
&& getMaxInactiveInterval() > 0) {
|
||||
token.setMaxInactives(System.currentTimeMillis()
|
||||
+ getMaxInactiveInterval() * 1000);
|
||||
newToken = true;
|
||||
}
|
||||
if (newToken && !token.isExpired()
|
||||
&& token != AuthenticationToken.ANONYMOUS) {
|
||||
String signedToken = signer.sign(token.toString());
|
||||
createAuthCookie(httpResponse, signedToken, getCookieDomain(),
|
||||
getCookiePath(), token.getExpires(),
|
||||
@ -628,12 +669,10 @@ protected void doFilter(FilterChain filterChain, HttpServletRequest request,
|
||||
* @param resp the response object.
|
||||
* @param token authentication token for the cookie.
|
||||
* @param domain the cookie domain.
|
||||
* @param path the cokie path.
|
||||
* @param path the cookie path.
|
||||
* @param expires UNIX timestamp that indicates the expire date of the
|
||||
* cookie. It has no effect if its value < 0.
|
||||
* @param isSecure is the cookie secure?
|
||||
* @param token the token.
|
||||
* @param expires the cookie expiration time.
|
||||
* @param isCookiePersistent whether the cookie is persistent or not.
|
||||
*
|
||||
* XXX the following code duplicate some logic in Jetty / Servlet API,
|
||||
|
@ -42,6 +42,7 @@ private AuthenticationToken() {
|
||||
|
||||
private AuthenticationToken(AuthToken token) {
|
||||
super(token.getUserName(), token.getName(), token.getType());
|
||||
setMaxInactives(token.getMaxInactives());
|
||||
setExpires(token.getExpires());
|
||||
}
|
||||
|
||||
@ -58,6 +59,17 @@ public AuthenticationToken(String userName, String principal, String type) {
|
||||
super(userName, principal, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max inactive time of the token.
|
||||
*
|
||||
* @param max inactive time of the token in milliseconds since the epoch.
|
||||
*/
|
||||
public void setMaxInactives(long maxInactives) {
|
||||
if (this != AuthenticationToken.ANONYMOUS) {
|
||||
super.setMaxInactives(maxInactives);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expiration of the token.
|
||||
*
|
||||
|
@ -34,15 +34,18 @@ public class AuthToken implements Principal {
|
||||
private static final String ATTR_SEPARATOR = "&";
|
||||
private static final String USER_NAME = "u";
|
||||
private static final String PRINCIPAL = "p";
|
||||
private static final String MAX_INACTIVES = "i";
|
||||
private static final String EXPIRES = "e";
|
||||
private static final String TYPE = "t";
|
||||
|
||||
private final static Set<String> ATTRIBUTES =
|
||||
new HashSet<String>(Arrays.asList(USER_NAME, PRINCIPAL, EXPIRES, TYPE));
|
||||
new HashSet<String>(Arrays.asList(USER_NAME, PRINCIPAL,
|
||||
MAX_INACTIVES, EXPIRES, TYPE));
|
||||
|
||||
private String userName;
|
||||
private String principal;
|
||||
private String type;
|
||||
private long maxInactives;
|
||||
private long expires;
|
||||
private String tokenStr;
|
||||
|
||||
@ -50,6 +53,7 @@ protected AuthToken() {
|
||||
userName = null;
|
||||
principal = null;
|
||||
type = null;
|
||||
maxInactives = -1;
|
||||
expires = -1;
|
||||
tokenStr = "ANONYMOUS";
|
||||
generateToken();
|
||||
@ -73,6 +77,7 @@ public AuthToken(String userName, String principal, String type) {
|
||||
this.userName = userName;
|
||||
this.principal = principal;
|
||||
this.type = type;
|
||||
this.maxInactives = -1;
|
||||
this.expires = -1;
|
||||
}
|
||||
|
||||
@ -88,6 +93,15 @@ protected static void checkForIllegalArgument(String value, String name) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max inactive interval of the token.
|
||||
*
|
||||
* @param max inactive interval of the token in milliseconds since the epoch.
|
||||
*/
|
||||
public void setMaxInactives(long interval) {
|
||||
this.maxInactives = interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expiration of the token.
|
||||
*
|
||||
@ -104,7 +118,10 @@ public void setExpires(long expires) {
|
||||
* @return true if the token has expired.
|
||||
*/
|
||||
public boolean isExpired() {
|
||||
return getExpires() != -1 && System.currentTimeMillis() > getExpires();
|
||||
return (getMaxInactives() != -1 &&
|
||||
System.currentTimeMillis() > getMaxInactives())
|
||||
|| (getExpires() != -1 &&
|
||||
System.currentTimeMillis() > getExpires());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,6 +132,8 @@ private void generateToken() {
|
||||
sb.append(USER_NAME).append("=").append(getUserName()).append(ATTR_SEPARATOR);
|
||||
sb.append(PRINCIPAL).append("=").append(getName()).append(ATTR_SEPARATOR);
|
||||
sb.append(TYPE).append("=").append(getType()).append(ATTR_SEPARATOR);
|
||||
sb.append(MAX_INACTIVES).append("=")
|
||||
.append(getMaxInactives()).append(ATTR_SEPARATOR);
|
||||
sb.append(EXPIRES).append("=").append(getExpires());
|
||||
tokenStr = sb.toString();
|
||||
}
|
||||
@ -147,6 +166,15 @@ public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max inactive time of the token.
|
||||
*
|
||||
* @return the max inactive time of the token, in milliseconds since Epoc.
|
||||
*/
|
||||
public long getMaxInactives() {
|
||||
return maxInactives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expiration time of the token.
|
||||
*
|
||||
@ -183,8 +211,10 @@ public static AuthToken parse(String tokenStr) throws AuthenticationException {
|
||||
if (!map.keySet().equals(ATTRIBUTES)) {
|
||||
throw new AuthenticationException("Invalid token string, missing attributes");
|
||||
}
|
||||
long maxInactives = Long.parseLong(map.get(MAX_INACTIVES));
|
||||
long expires = Long.parseLong(map.get(EXPIRES));
|
||||
AuthToken token = new AuthToken(map.get(USER_NAME), map.get(PRINCIPAL), map.get(TYPE));
|
||||
token.setMaxInactives(maxInactives);
|
||||
token.setExpires(expires);
|
||||
return token;
|
||||
}
|
||||
|
@ -18,11 +18,10 @@
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.net.HttpCookie;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
|
||||
@ -53,6 +52,7 @@
|
||||
public class TestAuthenticationFilter {
|
||||
|
||||
private static final long TOKEN_VALIDITY_SEC = 1000;
|
||||
private static final long TOKEN_MAX_INACTIVE_INTERVAL = 1000;
|
||||
|
||||
@Test
|
||||
public void testGetConfiguration() throws Exception {
|
||||
@ -595,7 +595,7 @@ private void _testDoFilterAuthentication(boolean withDomainPath,
|
||||
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
|
||||
FilterChain chain = Mockito.mock(FilterChain.class);
|
||||
|
||||
final HashMap<String, String> cookieMap = new HashMap<String, String>();
|
||||
final Map<String, String> cookieMap = new HashMap<String, String>();
|
||||
Mockito.doAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
@ -644,7 +644,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseCookieMap(String cookieHeader, HashMap<String,
|
||||
private static void parseCookieMap(String cookieHeader, Map<String,
|
||||
String> cookieMap) {
|
||||
List<HttpCookie> cookies = HttpCookie.parse(cookieHeader);
|
||||
for (HttpCookie cookie : cookies) {
|
||||
@ -761,7 +761,7 @@ public void testDoFilterAuthenticationFailure() throws Exception {
|
||||
|
||||
FilterChain chain = Mockito.mock(FilterChain.class);
|
||||
|
||||
final HashMap<String, String> cookieMap = new HashMap<String, String>();
|
||||
final Map<String, String> cookieMap = new HashMap<String, String>();
|
||||
Mockito.doAnswer(
|
||||
new Answer<Object>() {
|
||||
@Override
|
||||
@ -844,13 +844,164 @@ public void testDoFilterAuthenticatedExpired() throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
testDoFilterAuthenticationAuthorized() throws Exception {
|
||||
// Both expired period and MaxInActiveInterval are not reached.
|
||||
long maxInactives = System.currentTimeMillis()
|
||||
+ TOKEN_MAX_INACTIVE_INTERVAL;
|
||||
long expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
|
||||
boolean authorized = true;
|
||||
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
|
||||
expires,
|
||||
authorized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
testDoFilterAuthenticationUnauthorizedExpired() throws Exception {
|
||||
// Expired period is reached, MaxInActiveInterval is not reached.
|
||||
long maxInactives = System.currentTimeMillis()
|
||||
+ TOKEN_MAX_INACTIVE_INTERVAL;
|
||||
long expires = System.currentTimeMillis() - TOKEN_VALIDITY_SEC;
|
||||
boolean authorized = false;
|
||||
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
|
||||
expires,
|
||||
authorized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
testDoFilterAuthenticationUnauthorizedInactived() throws Exception {
|
||||
// Expired period is not reached, MaxInActiveInterval is reached.
|
||||
long maxInactives = System.currentTimeMillis()
|
||||
- TOKEN_MAX_INACTIVE_INTERVAL;
|
||||
long expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
|
||||
boolean authorized = false;
|
||||
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
|
||||
expires,
|
||||
authorized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
testDoFilterAuthenticationUnauthorizedInactivedExpired()
|
||||
throws Exception {
|
||||
// Both expired period and MaxInActiveInterval is reached.
|
||||
long maxInactives = System.currentTimeMillis()
|
||||
- TOKEN_MAX_INACTIVE_INTERVAL;
|
||||
long expires = System.currentTimeMillis() - TOKEN_VALIDITY_SEC;
|
||||
boolean authorized = false;
|
||||
_testDoFilterAuthenticationMaxInactiveInterval(maxInactives,
|
||||
expires,
|
||||
authorized);
|
||||
}
|
||||
|
||||
private void
|
||||
_testDoFilterAuthenticationMaxInactiveInterval(long maxInactives,
|
||||
long expires,
|
||||
boolean authorized)
|
||||
throws Exception {
|
||||
String secret = "secret";
|
||||
AuthenticationFilter filter = new AuthenticationFilter();
|
||||
try {
|
||||
FilterConfig config = Mockito.mock(FilterConfig.class);
|
||||
Mockito.when(config.getInitParameter("management.operation.return")).
|
||||
thenReturn("true");
|
||||
Mockito.when(config.getInitParameter(
|
||||
AuthenticationFilter.AUTH_TYPE)).thenReturn(
|
||||
DummyAuthenticationHandler.class.getName());
|
||||
Mockito.when(config.getInitParameter(
|
||||
AuthenticationFilter.SIGNATURE_SECRET)).thenReturn(secret);
|
||||
Mockito.when(config.getInitParameterNames()).thenReturn(
|
||||
new Vector<String>(
|
||||
Arrays.asList(AuthenticationFilter.AUTH_TYPE,
|
||||
AuthenticationFilter.SIGNATURE_SECRET,
|
||||
"management.operation.return")).elements());
|
||||
getMockedServletContextWithStringSigner(config);
|
||||
filter.init(config);
|
||||
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(request.getRequestURL()).thenReturn(
|
||||
new StringBuffer("http://foo:8080/bar"));
|
||||
|
||||
AuthenticationToken token = new AuthenticationToken("u", "p",
|
||||
DummyAuthenticationHandler.TYPE);
|
||||
token.setMaxInactives(maxInactives);
|
||||
token.setExpires(expires);
|
||||
|
||||
SignerSecretProvider secretProvider =
|
||||
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
|
||||
Properties secretProviderProps = new Properties();
|
||||
secretProviderProps.setProperty(
|
||||
AuthenticationFilter.SIGNATURE_SECRET, secret);
|
||||
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
|
||||
Signer signer = new Signer(secretProvider);
|
||||
String tokenSigned = signer.sign(token.toString());
|
||||
|
||||
Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, tokenSigned);
|
||||
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
|
||||
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
|
||||
Mockito.when(response.containsHeader("WWW-Authenticate"))
|
||||
.thenReturn(true);
|
||||
FilterChain chain = Mockito.mock(FilterChain.class);
|
||||
|
||||
if (authorized) {
|
||||
verifyAuthorized(filter, request, response, chain);
|
||||
} else {
|
||||
verifyUnauthorized(filter, request, response, chain);
|
||||
}
|
||||
} finally {
|
||||
filter.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyAuthorized(AuthenticationFilter filter,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain chain) throws
|
||||
Exception {
|
||||
final Map<String, String> cookieMap = new HashMap<>();
|
||||
Mockito.doAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
String cookieHeader = (String) invocation.getArguments()[1];
|
||||
parseCookieMap(cookieHeader, cookieMap);
|
||||
return null;
|
||||
}
|
||||
}).when(response).addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
String v = cookieMap.get(AuthenticatedURL.AUTH_COOKIE);
|
||||
Assert.assertNotNull("cookie missing", v);
|
||||
Assert.assertTrue(v.contains("u=") && v.contains("p=") && v.contains
|
||||
("t=") && v.contains("i=") && v.contains("e=")
|
||||
&& v.contains("s="));
|
||||
Mockito.verify(chain).doFilter(Mockito.any(ServletRequest.class),
|
||||
Mockito.any(ServletResponse.class));
|
||||
|
||||
SignerSecretProvider secretProvider =
|
||||
StringSignerSecretProviderCreator.newStringSignerSecretProvider();
|
||||
Properties secretProviderProps = new Properties();
|
||||
secretProviderProps.setProperty(
|
||||
AuthenticationFilter.SIGNATURE_SECRET, "secret");
|
||||
secretProvider.init(secretProviderProps, null, TOKEN_VALIDITY_SEC);
|
||||
Signer signer = new Signer(secretProvider);
|
||||
String value = signer.verifyAndExtract(v);
|
||||
AuthenticationToken token = AuthenticationToken.parse(value);
|
||||
assertThat(token.getMaxInactives(), not(0L));
|
||||
assertThat(token.getExpires(), not(0L));
|
||||
Assert.assertFalse("Token is expired.", token.isExpired());
|
||||
}
|
||||
|
||||
private static void verifyUnauthorized(AuthenticationFilter filter,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain chain) throws
|
||||
IOException,
|
||||
ServletException {
|
||||
final HashMap<String, String> cookieMap = new HashMap<String, String>();
|
||||
final Map<String, String> cookieMap = new HashMap<String, String>();
|
||||
Mockito.doAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
|
@ -41,13 +41,17 @@ The following properties should be in the `core-site.xml` of all the nodes in th
|
||||
|
||||
`hadoop.http.filter.initializers`: add to this property the `org.apache.hadoop.security.AuthenticationFilterInitializer` initializer class.
|
||||
|
||||
`hadoop.http.authentication.type`: Defines authentication used for the HTTP web-consoles. The supported values are: `simple` | `kerberos` | `#AUTHENTICATION_HANDLER_CLASSNAME#`. The dfeault value is `simple`.
|
||||
`hadoop.http.authentication.type`: Defines authentication used for the HTTP web-consoles. The supported values are: `simple` | `kerberos` | `#AUTHENTICATION_HANDLER_CLASSNAME#`. The default value is `simple`.
|
||||
|
||||
`hadoop.http.authentication.token.validity`: Indicates how long (in seconds) an authentication token is valid before it has to be renewed. The default value is `36000`.
|
||||
|
||||
`hadoop.http.authentication.token.MaxInactiveInterval`: Specifies the time, in seconds, between client requests the server will invalidate the token. The default value is `1800` (30 minutes).
|
||||
|
||||
`hadoop.http.authentication.signature.secret.file`: The signature secret file for signing the authentication tokens. The same secret should be used for all nodes in the cluster, JobTracker, NameNode, DataNode and TastTracker. The default value is `$user.home/hadoop-http-auth-signature-secret`. IMPORTANT: This file should be readable only by the Unix user running the daemons.
|
||||
|
||||
`hadoop.http.authentication.cookie.domain`: The domain to use for the HTTP cookie that stores the authentication token. In order to authentiation to work correctly across all nodes in the cluster the domain must be correctly set. There is no default value, the HTTP cookie will not have a domain working only with the hostname issuing the HTTP cookie.
|
||||
`hadoop.http.authentication.cookie.domain`: The domain to use for the HTTP cookie that stores the authentication token. In order to authentication to work correctly across all nodes in the cluster the domain must be correctly set. There is no default value, the HTTP cookie will not have a domain working only with the hostname issuing the HTTP cookie.
|
||||
|
||||
`hadoop.http.authentication.cookie.persistent`: Specifies the persistence of the HTTP cookie. If the value is true, the cookie is a persistent one. Otherwise, it is a session cookie. The default value is `false`(session cookie).
|
||||
|
||||
IMPORTANT: when using IP addresses, browsers ignore cookies with domain settings. For this setting to work properly all nodes in the cluster must be configured to generate URLs with `hostname.domain` names on it.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user