Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoakim Erdfelt2014-09-30 19:54:42 +0000
committerJoakim Erdfelt2014-09-30 19:54:42 +0000
commitd0fa66ddf0b13f754c6219120156fb66ab90268a (patch)
treeb51cc5a6eac5c784add0cd2877c73cefa5c21dc1 /jetty-server/src
parent93520df3f9d03814edba373beff4fea760219dc9 (diff)
downloadorg.eclipse.jetty.project-d0fa66ddf0b13f754c6219120156fb66ab90268a.tar.gz
org.eclipse.jetty.project-d0fa66ddf0b13f754c6219120156fb66ab90268a.tar.xz
org.eclipse.jetty.project-d0fa66ddf0b13f754c6219120156fb66ab90268a.zip
445542 - Add SecuredRedirectHandler for embedded jetty use to redirect to secure port/scheme
+ Adding SecuredRedirectHandler as option for those jetty embedded folks to have a simple http -> https solution (can even be setup and bound to specific connectors via the named virtualhosts concepts)
Diffstat (limited to 'jetty-server/src')
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/SecuredRedirectHandler.java66
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowAllVerifier.java31
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/SecuredRedirectHandlerTest.java288
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java9
4 files changed, 391 insertions, 3 deletions
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/SecuredRedirectHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/SecuredRedirectHandler.java
new file mode 100644
index 0000000000..756e15a6db
--- /dev/null
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/SecuredRedirectHandler.java
@@ -0,0 +1,66 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.server.handler;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.server.HttpChannel;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.util.URIUtil;
+
+/**
+ * Secured Redirect Handler
+ * <p>
+ * Using information present in the {@link HttpConfiguration}, will attempt to redirect to the {@link HttpConfiguration#getSecureScheme()} and
+ * {@link HttpConfiguration#getSecurePort()} for any request that {@link HttpServletRequest#isSecure()} == false.
+ */
+public class SecuredRedirectHandler extends AbstractHandler
+{
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ HttpConfiguration httpConfig = HttpChannel.getCurrentHttpChannel().getHttpConfiguration();
+
+ if (baseRequest.isSecure())
+ {
+ return; // all done
+ }
+
+ if (httpConfig.getSecurePort() > 0)
+ {
+ String scheme = httpConfig.getSecureScheme();
+ int port = httpConfig.getSecurePort();
+
+ String url = URIUtil.newURI(scheme,baseRequest.getServerName(),port,baseRequest.getRequestURI(),baseRequest.getQueryString());
+ response.setContentLength(0);
+ response.sendRedirect(url);
+ }
+ else
+ {
+ response.sendError(HttpStatus.FORBIDDEN_403,"Not Secure");
+ }
+ baseRequest.setHandled(true);
+ }
+} \ No newline at end of file
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowAllVerifier.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowAllVerifier.java
new file mode 100644
index 0000000000..0c203076f3
--- /dev/null
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowAllVerifier.java
@@ -0,0 +1,31 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.server.handler;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+
+public class AllowAllVerifier implements HostnameVerifier
+{
+ @Override
+ public boolean verify(String hostname, SSLSession session)
+ {
+ return true;
+ }
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/SecuredRedirectHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/SecuredRedirectHandlerTest.java
new file mode 100644
index 0000000000..ebcf20a1e5
--- /dev/null
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/SecuredRedirectHandlerTest.java
@@ -0,0 +1,288 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.server.handler;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URL;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.toolchain.test.IO;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SecuredRedirectHandlerTest
+{
+ private static Server server;
+ private static HostnameVerifier origVerifier;
+ private static SSLSocketFactory origSsf;
+ private static URI serverHttpUri;
+ private static URI serverHttpsUri;
+
+ @BeforeClass
+ public static void startServer() throws Exception
+ {
+ // Setup SSL
+ File keystore = MavenTestingUtils.getTestResourceFile("keystore");
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ sslContextFactory.setKeyStorePath(keystore.getAbsolutePath());
+ sslContextFactory.setKeyStorePassword("storepwd");
+ sslContextFactory.setKeyManagerPassword("keypwd");
+ sslContextFactory.setTrustStorePath(keystore.getAbsolutePath());
+ sslContextFactory.setTrustStorePassword("storepwd");
+
+ server = new Server();
+
+ int port = 12080;
+ int securePort = 12443;
+
+ // Setup HTTP Configuration
+ HttpConfiguration httpConf = new HttpConfiguration();
+ httpConf.setSecurePort(securePort);
+ httpConf.setSecureScheme("https");
+
+ ServerConnector httpConnector = new ServerConnector(server,new HttpConnectionFactory(httpConf));
+ httpConnector.setName("unsecured");
+ httpConnector.setPort(port);
+
+ // Setup HTTPS Configuration
+ HttpConfiguration httpsConf = new HttpConfiguration(httpConf);
+ httpsConf.addCustomizer(new SecureRequestCustomizer());
+
+ ServerConnector httpsConnector = new ServerConnector(server,new SslConnectionFactory(sslContextFactory,"http/1.1"),new HttpConnectionFactory(httpsConf));
+ httpsConnector.setName("secured");
+ httpsConnector.setPort(securePort);
+
+ // Add connectors
+ server.setConnectors(new Connector[] { httpConnector, httpsConnector });
+
+ // Wire up contexts
+ String secureHosts[] = new String[] { "@secured" };
+
+ ContextHandler test1Context = new ContextHandler();
+ test1Context.setContextPath("/test1");
+ test1Context.setHandler(new HelloHandler("Hello1"));
+ test1Context.setVirtualHosts(secureHosts);
+
+ ContextHandler test2Context = new ContextHandler();
+ test2Context.setContextPath("/test2");
+ test2Context.setHandler(new HelloHandler("Hello2"));
+ test2Context.setVirtualHosts(secureHosts);
+
+ ContextHandler rootContext = new ContextHandler();
+ rootContext.setContextPath("/");
+ rootContext.setHandler(new RootHandler("/test1","/test2"));
+ rootContext.setVirtualHosts(secureHosts);
+
+ // Wire up context for unsecure handling to only
+ // the named 'unsecured' connector
+ ContextHandler redirectHandler = new ContextHandler();
+ redirectHandler.setContextPath("/");
+ redirectHandler.setHandler(new SecuredRedirectHandler());
+ redirectHandler.setVirtualHosts(new String[] { "@unsecured" });
+
+ // Establish all handlers that have a context
+ ContextHandlerCollection contextHandlers = new ContextHandlerCollection();
+ contextHandlers.setHandlers(new Handler[] { redirectHandler, rootContext, test1Context, test2Context });
+
+ // Create server level handler tree
+ HandlerList handlers = new HandlerList();
+ handlers.addHandler(contextHandlers);
+ handlers.addHandler(new DefaultHandler()); // round things out
+
+ server.setHandler(handlers);
+
+ server.start();
+
+ // calculate serverUri
+ String host = httpConnector.getHost();
+ if (host == null)
+ {
+ host = "localhost";
+ }
+ serverHttpUri = new URI(String.format("http://%s:%d/",host,httpConnector.getLocalPort()));
+ serverHttpsUri = new URI(String.format("https://%s:%d/",host,httpsConnector.getLocalPort()));
+
+ origVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
+ origSsf = HttpsURLConnection.getDefaultSSLSocketFactory();
+
+ HttpsURLConnection.setDefaultHostnameVerifier(new AllowAllVerifier());
+ HttpsURLConnection.setDefaultSSLSocketFactory(sslContextFactory.getSslContext().getSocketFactory());
+ }
+
+ @AfterClass
+ public static void stopServer() throws Exception
+ {
+ HttpsURLConnection.setDefaultSSLSocketFactory(origSsf);
+ HttpsURLConnection.setDefaultHostnameVerifier(origVerifier);
+
+ server.stop();
+ server.join();
+ }
+
+ @Test
+ public void testRedirectUnsecuredRoot() throws Exception
+ {
+ URL url = serverHttpUri.resolve("/").toURL();
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setAllowUserInteraction(false);
+ assertThat("response code",connection.getResponseCode(),is(302));
+ assertThat("location header",connection.getHeaderField("Location"),is(serverHttpsUri.resolve("/").toASCIIString()));
+ connection.disconnect();
+ }
+
+ @Test
+ public void testRedirectSecuredRoot() throws Exception
+ {
+ URL url = serverHttpsUri.resolve("/").toURL();
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setAllowUserInteraction(false);
+ assertThat("response code",connection.getResponseCode(),is(200));
+ String content = getContent(connection);
+ assertThat("response content",content,containsString("<a href=\"/test1\">"));
+ connection.disconnect();
+ }
+
+ @Test
+ public void testAccessUnsecuredHandler() throws Exception
+ {
+ URL url = serverHttpUri.resolve("/test1").toURL();
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setAllowUserInteraction(false);
+ assertThat("response code",connection.getResponseCode(),is(302));
+ assertThat("location header",connection.getHeaderField("Location"),is(serverHttpsUri.resolve("/test1").toASCIIString()));
+ connection.disconnect();
+ }
+
+ @Test
+ public void testAccessUnsecured404() throws Exception
+ {
+ URL url = serverHttpUri.resolve("/nothing/here").toURL();
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setAllowUserInteraction(false);
+ assertThat("response code",connection.getResponseCode(),is(302));
+ assertThat("location header",connection.getHeaderField("Location"),is(serverHttpsUri.resolve("/nothing/here").toASCIIString()));
+ connection.disconnect();
+ }
+
+ @Test
+ public void testAccessSecured404() throws Exception
+ {
+ URL url = serverHttpsUri.resolve("/nothing/here").toURL();
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setAllowUserInteraction(false);
+ assertThat("response code",connection.getResponseCode(),is(404));
+ connection.disconnect();
+ }
+
+ private String getContent(HttpURLConnection connection) throws IOException
+ {
+ try (InputStream in = connection.getInputStream(); InputStreamReader reader = new InputStreamReader(in))
+ {
+ StringWriter writer = new StringWriter();
+ IO.copy(reader,writer);
+ return writer.toString();
+ }
+ }
+
+ public static class HelloHandler extends AbstractHandler
+ {
+ private final String msg;
+
+ public HelloHandler(String msg)
+ {
+ this.msg = msg;
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ response.setContentType("text/plain");
+ response.getWriter().printf("%s%n",msg);
+ baseRequest.setHandled(true);
+ }
+ }
+
+ public static class RootHandler extends AbstractHandler
+ {
+ private final String[] childContexts;
+
+ public RootHandler(String... children)
+ {
+ this.childContexts = children;
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ if (!"/".equals(target))
+ {
+ response.sendError(404);
+ return;
+ }
+
+ response.setContentType("text/html");
+ PrintWriter out = response.getWriter();
+ out.println("<html>");
+ out.println("<head><title>Contexts</title></head>");
+ out.println("<body>");
+ out.println("<h4>Child Contexts</h4>");
+ out.println("<ul>");
+ for (String child : childContexts)
+ {
+ out.printf("<li><a href=\"%s\">%s</a></li>%n",child,child);
+ }
+ out.println("</ul>");
+ out.println("</body></html>");
+ baseRequest.setHandled(true);
+ }
+ }
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java
index 0d39ab52a9..1942270e62 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslUploadTest.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.server.ssl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -40,6 +41,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.AfterClass;
@@ -58,12 +60,13 @@ public class SslUploadTest
@BeforeClass
public static void startServer() throws Exception
{
- String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
+ File keystore = MavenTestingUtils.getTestResourceFile("keystore");
+
SslContextFactory sslContextFactory = new SslContextFactory();
- sslContextFactory.setKeyStorePath(keystorePath);
+ sslContextFactory.setKeyStorePath(keystore.getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
- sslContextFactory.setTrustStorePath(keystorePath);
+ sslContextFactory.setTrustStorePath(keystore.getAbsolutePath());
sslContextFactory.setTrustStorePassword("storepwd");
server = new Server();

Back to the top