diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java index 4595e0fe992..3b7c2fd847f 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServlet.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.websocket.servlet; import java.io.IOException; +import java.lang.reflect.Constructor; import java.time.Duration; import javax.servlet.ServletContext; @@ -182,78 +183,6 @@ public abstract class WebSocketServlet extends HttpServlet return resources.getExtensionRegistry(); } - @Override - public Duration getIdleTimeout() - { - return getIdleTimeout(); - } - - @Override - public void setIdleTimeout(Duration duration) - { - setIdleTimeout(duration); - } - - @Override - public int getInputBufferSize() - { - return getInputBufferSize(); - } - - @Override - public void setInputBufferSize(int bufferSize) - { - setInputBufferSize(bufferSize); - } - - @Override - public long getMaxAllowedFrameSize() - { - return getMaxFrameSize(); - } - - @Override - public void setAllowedFrameSize(long maxFrameSize) - { - setMaxFrameSize(maxFrameSize); - } - - @Override - public long getMaxBinaryMessageSize() - { - return getMaxBinaryMessageSize(); - } - - @Override - public void setMaxBinaryMessageSize(long size) - { - setMaxBinaryMessageSize(size); - } - - @Override - public long getMaxTextMessageSize() - { - return getMaxTextMessageSize(); - } - - @Override - public void setMaxTextMessageSize(long size) - { - setMaxTextMessageSize(size); - } - - @Override - public int getOutputBufferSize() - { - return getOutputBufferSize(); - } - - @Override - public void setOutputBufferSize(int bufferSize) - { - setOutputBufferSize(bufferSize); - } - @Override public void addMapping(String pathSpec, WebSocketCreator creator) { @@ -274,6 +203,41 @@ public abstract class WebSocketServlet extends HttpServlet mapping.addMapping(pathSpec, creator, frameHandlerFactory, this); } + @Override + public void register(Class endpointClass) + { + Constructor constructor; + try + { + constructor = endpointClass.getDeclaredConstructor(null); + } + catch (NoSuchMethodException e) + { + throw new RuntimeException(e); + } + + WebSocketCreator creator = (req, resp) -> + { + try + { + return constructor.newInstance(); + } + catch (Throwable t) + { + t.printStackTrace(); + return null; + } + }; + + addMapping("/", creator); + } + + @Override + public void setCreator(WebSocketCreator creator) + { + addMapping("/", creator); + } + @Override public WebSocketCreator getMapping(PathSpec pathSpec) { diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java index f14b9f90146..d3b20236d9e 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketServletFactory.java @@ -36,9 +36,9 @@ public interface WebSocketServletFactory void setInputBufferSize(int bufferSize); - long getMaxAllowedFrameSize(); + long getMaxFrameSize(); - void setAllowedFrameSize(long maxFrameSize); + void setMaxFrameSize(long maxFrameSize); long getMaxBinaryMessageSize(); @@ -72,6 +72,20 @@ public interface WebSocketServletFactory */ void addMapping(PathSpec pathSpec, WebSocketCreator creator); + /** + * Add a WebSocket mapping at PathSpec "/" for a creator which creates the endpointClass + * + * @param endpointClass the WebSocket class to use + */ + void register(Class endpointClass); + + /** + * Add a WebSocket mapping at PathSpec "/" for a creator + * + * @param creator the WebSocketCreator to use + */ + void setCreator(WebSocketCreator creator); + /** * Returns the creator for the given path spec. * diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/internal/UpgradeHttpServletRequest.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/internal/UpgradeHttpServletRequest.java index 21b47fb9fed..50c3611c3a9 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/internal/UpgradeHttpServletRequest.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/internal/UpgradeHttpServletRequest.java @@ -18,6 +18,19 @@ package org.eclipse.jetty.websocket.servlet.internal; +import java.io.BufferedReader; +import java.net.InetSocketAddress; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.TreeMap; + import javax.servlet.AsyncContext; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; @@ -31,18 +44,10 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpUpgradeHandler; import javax.servlet.http.Part; -import java.io.BufferedReader; -import java.net.InetSocketAddress; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TreeMap; + +import org.eclipse.jetty.server.Authentication; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.UserIdentity; /** * An immutable, feature limited, HttpServletRequest that will not be recycled by Jetty. @@ -67,6 +72,8 @@ public class UpgradeHttpServletRequest implements HttpServletRequest private final Cookie[] cookies; private final String remoteUser; private final Principal principal; + private final Authentication authentication; + private final UserIdentity.Scope scope; private final Map> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private final Map parameters = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @@ -104,6 +111,8 @@ public class UpgradeHttpServletRequest implements HttpServletRequest remoteUser = httpRequest.getRemoteUser(); principal = httpRequest.getUserPrincipal(); + authentication = Request.getBaseRequest(httpRequest).getAuthentication(); + scope = Request.getBaseRequest(httpRequest).getUserIdentityScope(); Enumeration headerNames = httpRequest.getHeaderNames(); while (headerNames.hasMoreElements()) @@ -220,7 +229,10 @@ public class UpgradeHttpServletRequest implements HttpServletRequest @Override public boolean isUserInRole(String role) { - throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE); + if (authentication instanceof Authentication.User) + return ((Authentication.User)authentication).isUserInRole(scope, role); + + return false; } @Override diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebsocketTest.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebsocketTest.java index 0d59c5858be..42bbf1b10c1 100644 --- a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebsocketTest.java +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/JettyWebsocketTest.java @@ -47,34 +47,26 @@ public class JettyWebsocketTest public static class EventSocket { CountDownLatch closed = new CountDownLatch(1); - String id; - public EventSocket() - { - id = ""; - } - - public EventSocket(String id) - { - this.id = id; - } + String behavior; @OnWebSocketConnect public void onOpen(Session sess) { - System.out.println("["+id+"]Socket Connected: " + sess); + behavior = sess.getPolicy().getBehavior().name(); + System.err.println(toString() + " Socket Connected: " + sess); } @OnWebSocketMessage public void onMessage(String message) { - System.out.println("["+id+"]Received TEXT message: " + message); + System.err.println(toString() + " Received TEXT message: " + message); } @OnWebSocketClose public void onClose(int statusCode, String reason) { - System.out.println("["+id+"]Socket Closed: " + statusCode + ":" + reason); + System.err.println(toString() + " Socket Closed: " + statusCode + ":" + reason); closed.countDown(); } @@ -83,25 +75,20 @@ public class JettyWebsocketTest { cause.printStackTrace(System.err); } - } - public static class MyWebSocketServlet1 extends WebSocketServlet - { @Override - public void configure(WebSocketServletFactory factory) + public String toString() { - System.err.println("Configuring MyWebSocketServlet1"); - factory.addMapping("/",(req, resp)->new EventSocket("MyWebSocketServlet1")); + return String.format("[%s@%s]", behavior, Integer.toHexString(hashCode())); } } - public static class MyWebSocketServlet2 extends WebSocketServlet + public static class MyWebSocketServlet extends WebSocketServlet { @Override public void configure(WebSocketServletFactory factory) { - System.err.println("Configuring MyWebSocketServlet2"); - factory.addMapping("/",(req, resp)->new EventSocket("MyWebSocketServlet2")); + factory.addMapping("/",(req, resp)->new EventSocket()); } } @@ -118,20 +105,18 @@ public class JettyWebsocketTest contextHandler.setContextPath("/"); server.setHandler(contextHandler); - contextHandler.addServlet(MyWebSocketServlet1.class, "/testPath1"); - contextHandler.addServlet(MyWebSocketServlet2.class, "/testPath2"); + contextHandler.addServlet(MyWebSocketServlet.class, "/testPath1"); + contextHandler.addServlet(MyWebSocketServlet.class, "/testPath2"); try { JettyWebSocketServletContainerInitializer.configure(contextHandler); server.start(); - URI uri = URI.create("ws://localhost:8080/testPath1"); - WebSocketClient client = new WebSocketClient(); client.start(); - + URI uri = URI.create("ws://localhost:8080/testPath1"); EventSocket socket = new EventSocket(); CompletableFuture connect = client.connect(socket, uri); try(Session session = connect.get(5, TimeUnit.SECONDS)) diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketServletExamplesTest.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketServletExamplesTest.java new file mode 100644 index 00000000000..869478bd726 --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketServletExamplesTest.java @@ -0,0 +1,226 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 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.websocket.tests; + +import java.net.URI; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.client.api.AuthenticationStore; +import org.eclipse.jetty.client.util.BasicAuthentication; +import org.eclipse.jetty.security.ConstraintMapping; +import org.eclipse.jetty.security.ConstraintSecurityHandler; +import org.eclipse.jetty.security.HashLoginService; +import org.eclipse.jetty.security.SecurityHandler; +import org.eclipse.jetty.security.UserStore; +import org.eclipse.jetty.security.authentication.BasicAuthenticator; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.security.Constraint; +import org.eclipse.jetty.util.security.Credential; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.UpgradeRequest; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; +import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.server.JettyWebSocketServletContainerInitializer; +import org.eclipse.jetty.websocket.tests.examples.MyAdvancedEchoServlet; +import org.eclipse.jetty.websocket.tests.examples.MyAuthedServlet; +import org.eclipse.jetty.websocket.tests.examples.MyEchoServlet; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class WebSocketServletExamplesTest +{ + + @WebSocket + public static class ClientSocket + { + CountDownLatch closed = new CountDownLatch(1); + ArrayBlockingQueue messageQueue = new ArrayBlockingQueue<>(2); + + @OnWebSocketConnect + public void onOpen(Session sess) + { + System.err.println("ClientSocket Connected: " + sess); + } + + @OnWebSocketMessage + public void onMessage(String message) + { + messageQueue.offer(message); + System.err.println("Received TEXT message: " + message); + } + + @OnWebSocketClose + public void onClose(int statusCode, String reason) + { + System.err.println("ClientSocket Closed: " + statusCode + ":" + reason); + closed.countDown(); + } + + @OnWebSocketError + public void onError(Throwable cause) + { + cause.printStackTrace(System.err); + } + } + + + static Server _server; + static ServletContextHandler _context; + + @BeforeAll + public static void setup() throws Exception + { + _server = new Server(); + ServerConnector connector = new ServerConnector(_server); + connector.setPort(8080); + _server.addConnector(connector); + + _context = new ServletContextHandler(ServletContextHandler.SESSIONS); + _context.setContextPath("/"); + _context.setSecurityHandler(getSecurityHandler("user", "password", "testRealm")); + _server.setHandler(_context); + + _context.addServlet(MyEchoServlet.class, "/echo"); + _context.addServlet(MyAdvancedEchoServlet.class, "/advancedEcho"); + _context.addServlet(MyAuthedServlet.class, "/authed"); + + JettyWebSocketServletContainerInitializer.configure(_context); + _server.start(); + } + + @AfterAll + public static void stop() throws Exception + { + _server.stop(); + } + + private static SecurityHandler getSecurityHandler(String username, String password, String realm) { + + HashLoginService loginService = new HashLoginService(); + UserStore userStore = new UserStore(); + userStore.addUser(username, Credential.getCredential(password), new String[] {"websocket"}); + loginService.setUserStore(userStore); + loginService.setName(realm); + + Constraint constraint = new Constraint(); + constraint.setName("auth"); + constraint.setAuthenticate(true); + constraint.setRoles(new String[]{"**"}); + + ConstraintMapping mapping = new ConstraintMapping(); + mapping.setPathSpec("/authed/*"); + mapping.setConstraint(constraint); + + ConstraintSecurityHandler security = new ConstraintSecurityHandler(); + security.addConstraintMapping(mapping); + security.setAuthenticator(new BasicAuthenticator()); + security.setLoginService(loginService); + + return security; + } + + + @Test + public void testEchoServlet() throws Exception + { + WebSocketClient client = new WebSocketClient(); + client.start(); + + URI uri = URI.create("ws://localhost:8080/echo"); + ClientSocket socket = new ClientSocket(); + CompletableFuture connect = client.connect(socket, uri); + try (Session session = connect.get(5, TimeUnit.SECONDS)) + { + String message = "hello world"; + session.getRemote().sendString(message); + + String response = socket.messageQueue.poll(5, TimeUnit.SECONDS); + assertThat(response, is(message)); + } + + assertTrue(socket.closed.await(10, TimeUnit.SECONDS)); + } + + + @Test + public void testAdvancedEchoServlet() throws Exception + { + WebSocketClient client = new WebSocketClient(); + client.start(); + + URI uri = URI.create("ws://localhost:8080/advancedEcho"); + ClientSocket socket = new ClientSocket(); + + UpgradeRequest upgradeRequest = new ClientUpgradeRequest(); + upgradeRequest.setSubProtocols("text"); + CompletableFuture connect = client.connect(socket, uri, upgradeRequest); + try (Session session = connect.get(5, TimeUnit.SECONDS)) + { + String message = "hello world"; + session.getRemote().sendString(message); + + String response = socket.messageQueue.poll(5, TimeUnit.SECONDS); + assertThat(response, is(message)); + } + + assertTrue(socket.closed.await(10, TimeUnit.SECONDS)); + } + + + @Test + public void testAuthedServlet() throws Exception + { + WebSocketClient client = new WebSocketClient(); + client.start(); + AuthenticationStore authenticationStore = client.getHttpClient().getAuthenticationStore(); + + URI uri = URI.create("ws://localhost:8080/authed"); + + BasicAuthentication basicAuthentication = new BasicAuthentication(uri, "testRealm", "user", "password"); + authenticationStore.addAuthentication(basicAuthentication); + + ClientSocket socket = new ClientSocket(); + CompletableFuture connect = client.connect(socket, uri); + try (Session session = connect.get(5, TimeUnit.SECONDS)) + { + String message = "hello world"; + session.getRemote().sendString(message); + + String response = socket.messageQueue.poll(5, TimeUnit.SECONDS); + assertThat(response, is(message)); + } + + assertTrue(socket.closed.await(10, TimeUnit.SECONDS)); + } +} diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAdvancedEchoCreator.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAdvancedEchoCreator.java new file mode 100644 index 00000000000..c1c85693aef --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAdvancedEchoCreator.java @@ -0,0 +1,57 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.websocket.tests.examples; + +import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; +import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; +import org.eclipse.jetty.websocket.servlet.WebSocketCreator; + +public class MyAdvancedEchoCreator implements WebSocketCreator +{ + private MyBinaryEchoSocket binaryEcho; + private MyEchoSocket textEcho; + + public MyAdvancedEchoCreator() + { + // Create the reusable sockets + this.binaryEcho = new MyBinaryEchoSocket(); + this.textEcho = new MyEchoSocket(); + } + + @Override + public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) + { + for (String subprotocol : req.getSubProtocols()) + { + if ("binary".equals(subprotocol)) + { + resp.setAcceptedSubProtocol(subprotocol); + return binaryEcho; + } + if ("text".equals(subprotocol)) + { + resp.setAcceptedSubProtocol(subprotocol); + return textEcho; + } + } + + // No valid subprotocol in request, ignore the request + return null; + } +} diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAdvancedEchoServlet.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAdvancedEchoServlet.java new file mode 100644 index 00000000000..306b98ac954 --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAdvancedEchoServlet.java @@ -0,0 +1,41 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.websocket.tests.examples; + +import java.time.Duration; + +import javax.servlet.annotation.WebServlet; + +import org.eclipse.jetty.websocket.servlet.WebSocketServlet; +import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; + +@SuppressWarnings("serial") +@WebServlet(name = "MyAdvanced Echo WebSocket Servlet", urlPatterns = { "/advecho" }) +public class MyAdvancedEchoServlet extends WebSocketServlet +{ + @Override + public void configure(WebSocketServletFactory factory) + { + // set a 10 second timeout + factory.setIdleTimeout(Duration.ofSeconds(10)); + + // set a custom WebSocket creator + factory.setCreator(new MyAdvancedEchoCreator()); + } +} \ No newline at end of file diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAuthedCreator.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAuthedCreator.java new file mode 100644 index 00000000000..94b13ac76d6 --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAuthedCreator.java @@ -0,0 +1,60 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.websocket.tests.examples; + +import java.io.IOException; +import java.security.Principal; + +import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; +import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; +import org.eclipse.jetty.websocket.servlet.WebSocketCreator; + +public class MyAuthedCreator implements WebSocketCreator +{ + @Override + public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) + { + try + { + // Is Authenticated? + Principal principal = req.getUserPrincipal(); + if (principal == null) + { + resp.sendForbidden("Not authenticated yet"); + return null; + } + + // Is Authorized? + if (!req.isUserInRole("websocket")) + { + resp.sendForbidden("Not authenticated yet"); + return null; + } + + // Return websocket + return new MyEchoSocket(); + } + catch (IOException e) + { + e.printStackTrace(System.err); + } + // no websocket + return null; + } +} diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAuthedServlet.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAuthedServlet.java new file mode 100644 index 00000000000..7dae124e0a3 --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyAuthedServlet.java @@ -0,0 +1,32 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.websocket.tests.examples; + +import org.eclipse.jetty.websocket.servlet.WebSocketServlet; +import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; + +@SuppressWarnings("serial") +public class MyAuthedServlet extends WebSocketServlet +{ + @Override + public void configure(WebSocketServletFactory factory) + { + factory.setCreator(new MyAuthedCreator()); + } +} diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyBinaryEchoSocket.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyBinaryEchoSocket.java new file mode 100644 index 00000000000..9427594dca8 --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyBinaryEchoSocket.java @@ -0,0 +1,39 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.websocket.tests.examples; + +import java.nio.ByteBuffer; + +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; + +/** + * Echo BINARY messages + */ +@WebSocket +public class MyBinaryEchoSocket +{ + @OnWebSocketMessage + public void onWebSocketText(Session session, byte buf[], int offset, int len) + { + // Echo message back, asynchronously + session.getRemote().sendBytes(ByteBuffer.wrap(buf,offset,len), null); + } +} diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyEchoServlet.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyEchoServlet.java new file mode 100644 index 00000000000..2be7d88fc7d --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyEchoServlet.java @@ -0,0 +1,41 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.websocket.tests.examples; + +import java.time.Duration; + +import javax.servlet.annotation.WebServlet; + +import org.eclipse.jetty.websocket.servlet.WebSocketServlet; +import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; + +@SuppressWarnings("serial") +@WebServlet(name = "MyEcho WebSocket Servlet", urlPatterns = { "/echo" }) +public class MyEchoServlet extends WebSocketServlet +{ + @Override + public void configure(WebSocketServletFactory factory) + { + // set a 10 second timeout + factory.setIdleTimeout(Duration.ofSeconds(10)); + + // register MyEchoSocket as the WebSocket to create on Upgrade + factory.register(MyEchoSocket.class); + } +} diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyEchoSocket.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyEchoSocket.java new file mode 100644 index 00000000000..835c086d56f --- /dev/null +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/examples/MyEchoSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2017 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.websocket.tests.examples; + +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; + +/** + * Example WebSocket, simple echo + */ +@WebSocket +public class MyEchoSocket +{ + @OnWebSocketMessage + public void onWebSocketText(Session session, String message) + { + // Echo message back, asynchronously + session.getRemote().sendString(message, null); + } +}