diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java index 4ec620ad47e..a905020b8b3 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java @@ -55,10 +55,7 @@ import org.apache.hadoop.conf.ConfServlet; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeys; import org.apache.hadoop.security.AuthenticationFilterInitializer; -import org.apache.hadoop.security.authentication.util.FileSignerSecretProvider; -import org.apache.hadoop.security.authentication.util.RandomSignerSecretProvider; import org.apache.hadoop.security.authentication.util.SignerSecretProvider; -import org.apache.hadoop.security.authentication.util.ZKSignerSecretProvider; import org.apache.hadoop.security.ssl.SslSocketConnectorSecure; import org.apache.hadoop.jmx.JMXJsonServlet; import org.apache.hadoop.log.LogLevel; @@ -98,8 +95,6 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.sun.jersey.spi.container.servlet.ServletContainer; -import static org.apache.hadoop.security.authentication.server - .AuthenticationFilter.*; /** * Create a Jetty embedded server to answer http requests. The primary goal is * to serve up status information for the server. There are three contexts: @@ -1152,9 +1147,11 @@ public final class HttpServer2 implements FilterContainer { /** * A Servlet input filter that quotes all HTML active characters in the * parameter names and values. The goal is to quote the characters to make - * all of the servlets resistant to cross-site scripting attacks. + * all of the servlets resistant to cross-site scripting attacks. It also + * sets X-FRAME-OPTIONS in the header to mitigate clickjacking attacks. */ public static class QuotingInputFilter implements Filter { + private static final XFrameOption X_FRAME_OPTION = XFrameOption.SAMEORIGIN; private FilterConfig config; public static class RequestQuoter extends HttpServletRequestWrapper { @@ -1274,6 +1271,7 @@ public final class HttpServer2 implements FilterContainer { } else if (mime.startsWith("application/xml")) { httpResponse.setContentType("text/xml; charset=utf-8"); } + httpResponse.addHeader("X-FRAME-OPTIONS", X_FRAME_OPTION.toString()); chain.doFilter(quoted, httpResponse); } @@ -1290,4 +1288,23 @@ public final class HttpServer2 implements FilterContainer { } } + + /** + * The X-FRAME-OPTIONS header in HTTP response to mitigate clickjacking + * attack. + */ + public enum XFrameOption { + DENY("DENY") , SAMEORIGIN ("SAMEORIGIN"), ALLOWFROM ("ALLOW-FROM"); + + XFrameOption(String name) { + this.name = name; + } + + private final String name; + + @Override + public String toString() { + return this.name; + } + } } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java index 5b202da0eb4..9b279410dd2 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServer.java @@ -235,6 +235,16 @@ public class TestHttpServer extends HttpServerFunctionalTest { assertEquals("text/html; charset=utf-8", conn.getContentType()); } + @Test + public void testHttpResonseContainsXFrameOptions() throws IOException { + URL url = new URL(baseUrl, ""); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.connect(); + + String xfoHeader = conn.getHeaderField("X-FRAME-OPTIONS"); + assertTrue("X-FRAME-OPTIONS is absent in the header", xfoHeader != null); + } + /** * Dummy filter that mimics as an authentication filter. Obtains user identity * from the request parameter user.name. Wraps around the request so that