You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by be...@apache.org on 2015/06/25 01:00:05 UTC
hadoop git commit: HADOOP-12049. Control http authentication cookie
persistence via configuration. Contributed by Huizhi Lu.
Repository: hadoop
Updated Branches:
refs/heads/trunk afe9ea3c1 -> a815cc157
HADOOP-12049. Control http authentication cookie persistence via configuration. Contributed by Huizhi Lu.
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/a815cc15
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/a815cc15
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/a815cc15
Branch: refs/heads/trunk
Commit: a815cc157ceb24e02189634a85abed8e874568e0
Parents: afe9ea3
Author: Benoy Antony <be...@apache.org>
Authored: Wed Jun 24 15:59:39 2015 -0700
Committer: Benoy Antony <be...@apache.org>
Committed: Wed Jun 24 15:59:39 2015 -0700
----------------------------------------------------------------------
.../server/AuthenticationFilter.java | 28 ++-
.../http/TestAuthenticationSessionCookie.java | 187 +++++++++++++++++++
.../apache/hadoop/http/TestHttpCookieFlag.java | 2 +-
3 files changed, 213 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/a815cc15/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java
index 0f86623..bf44f48 100644
--- a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java
+++ b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java
@@ -161,6 +161,12 @@ public class AuthenticationFilter implements Filter {
public static final String COOKIE_PATH = "cookie.path";
/**
+ * Constant for the configuration property
+ * that indicates the persistence of the HTTP cookie.
+ */
+ public static final String COOKIE_PERSISTENT = "cookie.persistent";
+
+ /**
* Constant for the configuration property that indicates the name of the
* SignerSecretProvider class to use.
* Possible values are: "string", "random", "zookeeper", or a classname.
@@ -187,6 +193,7 @@ public class AuthenticationFilter implements Filter {
private long validity;
private String cookieDomain;
private String cookiePath;
+ private boolean isCookiePersistent;
private boolean isInitializedByTomcat;
/**
@@ -228,6 +235,9 @@ public class AuthenticationFilter implements Filter {
cookieDomain = config.getProperty(COOKIE_DOMAIN, null);
cookiePath = config.getProperty(COOKIE_PATH, null);
+ isCookiePersistent = Boolean.parseBoolean(
+ config.getProperty(COOKIE_PERSISTENT, "false"));
+
}
protected void initializeAuthHandler(String authHandlerClassName, FilterConfig filterConfig)
@@ -372,6 +382,15 @@ public class AuthenticationFilter implements Filter {
}
/**
+ * Returns the cookie persistence to use for the HTTP cookie.
+ *
+ * @return the cookie persistence to use for the HTTP cookie.
+ */
+ protected boolean isCookiePersistent() {
+ return isCookiePersistent;
+ }
+
+ /**
* Destroys the filter.
* <p>
* It invokes the {@link AuthenticationHandler#destroy()} method to release any resources it may hold.
@@ -549,7 +568,8 @@ public class AuthenticationFilter implements Filter {
if (newToken && !token.isExpired() && token != AuthenticationToken.ANONYMOUS) {
String signedToken = signer.sign(token.toString());
createAuthCookie(httpResponse, signedToken, getCookieDomain(),
- getCookiePath(), token.getExpires(), isHttps);
+ getCookiePath(), token.getExpires(),
+ isCookiePersistent(), isHttps);
}
doFilter(filterChain, httpRequest, httpResponse);
}
@@ -569,7 +589,7 @@ public class AuthenticationFilter implements Filter {
if (unauthorizedResponse) {
if (!httpResponse.isCommitted()) {
createAuthCookie(httpResponse, "", getCookieDomain(),
- getCookiePath(), 0, isHttps);
+ getCookiePath(), 0, isCookiePersistent(), isHttps);
// If response code is 401. Then WWW-Authenticate Header should be
// present.. reset to 403 if not found..
if ((errCode == HttpServletResponse.SC_UNAUTHORIZED)
@@ -614,6 +634,7 @@ public class AuthenticationFilter implements Filter {
* @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,
* because of the fact that Hadoop is stuck at servlet 2.5 and jetty 6
@@ -621,6 +642,7 @@ public class AuthenticationFilter implements Filter {
*/
public static void createAuthCookie(HttpServletResponse resp, String token,
String domain, String path, long expires,
+ boolean isCookiePersistent,
boolean isSecure) {
StringBuilder sb = new StringBuilder(AuthenticatedURL.AUTH_COOKIE)
.append("=");
@@ -636,7 +658,7 @@ public class AuthenticationFilter implements Filter {
sb.append("; Domain=").append(domain);
}
- if (expires >= 0) {
+ if (expires >= 0 && isCookiePersistent) {
Date date = new Date(expires);
SimpleDateFormat df = new SimpleDateFormat("EEE, " +
"dd-MMM-yyyy HH:mm:ss zzz");
http://git-wip-us.apache.org/repos/asf/hadoop/blob/a815cc15/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestAuthenticationSessionCookie.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestAuthenticationSessionCookie.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestAuthenticationSessionCookie.java
new file mode 100644
index 0000000..e435034
--- /dev/null
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestAuthenticationSessionCookie.java
@@ -0,0 +1,187 @@
+/**
+ * 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.http;
+
+import org.junit.Assert;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
+import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
+import org.junit.After;
+import org.junit.Test;
+import org.mortbay.log.Log;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URL;
+import java.net.HttpCookie;
+import java.util.List;
+
+public class TestAuthenticationSessionCookie {
+ private static final String BASEDIR = System.getProperty("test.build.dir",
+ "target/test-dir") + "/" + TestHttpCookieFlag.class.getSimpleName();
+ private static boolean isCookiePersistent;
+ private static final long TOKEN_VALIDITY_SEC = 1000;
+ private static long expires;
+ private static String keystoresDir;
+ private static String sslConfDir;
+ private static HttpServer2 server;
+
+ public static class DummyAuthenticationFilter implements Filter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ isCookiePersistent = false;
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException,
+ ServletException {
+ HttpServletResponse resp = (HttpServletResponse) response;
+ AuthenticationFilter.createAuthCookie(resp, "token", null, null, expires,
+ isCookiePersistent, true);
+ chain.doFilter(request, resp);
+ }
+
+ @Override
+ public void destroy() {
+ }
+ }
+
+ public static class DummyFilterInitializer extends FilterInitializer {
+ @Override
+ public void initFilter(FilterContainer container, Configuration conf) {
+ container.addFilter("DummyAuth", DummyAuthenticationFilter.class
+ .getName(), null);
+ }
+ }
+
+ public static class Dummy2AuthenticationFilter
+ extends DummyAuthenticationFilter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ isCookiePersistent = true;
+ expires = System.currentTimeMillis() + TOKEN_VALIDITY_SEC;
+ }
+
+ @Override
+ public void destroy() {
+ }
+ }
+
+ public static class Dummy2FilterInitializer extends FilterInitializer {
+ @Override
+ public void initFilter(FilterContainer container, Configuration conf) {
+ container.addFilter("Dummy2Auth", Dummy2AuthenticationFilter.class
+ .getName(), null);
+ }
+ }
+
+ public void startServer(boolean isTestSessionCookie) throws Exception {
+ Configuration conf = new Configuration();
+ if (isTestSessionCookie) {
+ conf.set(HttpServer2.FILTER_INITIALIZER_PROPERTY,
+ DummyFilterInitializer.class.getName());
+ } else {
+ conf.set(HttpServer2.FILTER_INITIALIZER_PROPERTY,
+ Dummy2FilterInitializer.class.getName());
+ }
+
+ File base = new File(BASEDIR);
+ FileUtil.fullyDelete(base);
+ base.mkdirs();
+ keystoresDir = new File(BASEDIR).getAbsolutePath();
+ sslConfDir = KeyStoreTestUtil.getClasspathDir(TestSSLHttpServer.class);
+
+ KeyStoreTestUtil.setupSSLConfig(keystoresDir, sslConfDir, conf, false);
+ Configuration sslConf = new Configuration(false);
+ sslConf.addResource("ssl-server.xml");
+ sslConf.addResource("ssl-client.xml");
+
+
+ server = new HttpServer2.Builder()
+ .setName("test")
+ .addEndpoint(new URI("http://localhost"))
+ .addEndpoint(new URI("https://localhost"))
+ .setConf(conf)
+ .keyPassword(sslConf.get("ssl.server.keystore.keypassword"))
+ .keyStore(sslConf.get("ssl.server.keystore.location"),
+ sslConf.get("ssl.server.keystore.password"),
+ sslConf.get("ssl.server.keystore.type", "jks"))
+ .trustStore(sslConf.get("ssl.server.truststore.location"),
+ sslConf.get("ssl.server.truststore.password"),
+ sslConf.get("ssl.server.truststore.type", "jks")).build();
+ server.addServlet("echo", "/echo", TestHttpServer.EchoServlet.class);
+ server.start();
+ }
+
+ @Test
+ public void testSessionCookie() throws IOException {
+ try {
+ startServer(true);
+ } catch (Exception e) {
+ // Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ URL base = new URL("http://" + NetUtils.getHostPortString(server
+ .getConnectorAddress(0)));
+ HttpURLConnection conn = (HttpURLConnection) new URL(base,
+ "/echo").openConnection();
+
+ String header = conn.getHeaderField("Set-Cookie");
+ List<HttpCookie> cookies = HttpCookie.parse(header);
+ Assert.assertTrue(!cookies.isEmpty());
+ Log.info(header);
+ Assert.assertFalse(header.contains("; Expires="));
+ Assert.assertTrue("token".equals(cookies.get(0).getValue()));
+ }
+
+ @Test
+ public void testPersistentCookie() throws IOException {
+ try {
+ startServer(false);
+ } catch (Exception e) {
+ // Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ URL base = new URL("http://" + NetUtils.getHostPortString(server
+ .getConnectorAddress(0)));
+ HttpURLConnection conn = (HttpURLConnection) new URL(base,
+ "/echo").openConnection();
+
+ String header = conn.getHeaderField("Set-Cookie");
+ List<HttpCookie> cookies = HttpCookie.parse(header);
+ Assert.assertTrue(!cookies.isEmpty());
+ Log.info(header);
+ Assert.assertTrue(header.contains("; Expires="));
+ Assert.assertTrue("token".equals(cookies.get(0).getValue()));
+ }
+
+ @After
+ public void cleanup() throws Exception {
+ server.stop();
+ FileUtil.fullyDelete(new File(BASEDIR));
+ KeyStoreTestUtil.cleanupSSLConfig(keystoresDir, sslConfDir);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/a815cc15/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
index 75a9480..5c5ed48 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
@@ -60,7 +60,7 @@ public class TestHttpCookieFlag {
HttpServletResponse resp = (HttpServletResponse) response;
boolean isHttps = "https".equals(request.getScheme());
AuthenticationFilter.createAuthCookie(resp, "token", null, null, -1,
- isHttps);
+ true, isHttps);
chain.doFilter(request, resp);
}