Integrate web sockets with CMS session
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 9 May 2019 07:49:51 +0000 (09:49 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 9 May 2019 07:49:51 +0000 (09:49 +0200)
org.argeo.ext.equinox.jetty/bnd.bnd
org.argeo.ext.equinox.jetty/pom.xml
org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/WebSocketJettyCustomizer.java

index 8b1b7146d7f1a2c315b703142489e2165ef7c7d8..0f21e73c91b7983885c8fd8a02d555762177a708 100644 (file)
@@ -3,4 +3,5 @@ Fragment-Host: org.eclipse.equinox.http.jetty
 Import-Package: org.eclipse.jetty.websocket.jsr356,\
 org.eclipse.jetty.websocket.api,\
 org.eclipse.jetty.websocket.common,\
+org.osgi.service.http,\
 *
\ No newline at end of file
index 2c71d6f614a96d1e96b35496b641fef4f06bc226..491c5e5586c67ac0bc2ba0ca7c784f87465debd5 100644 (file)
@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.argeo.commons</groupId>
@@ -9,4 +11,11 @@
        </parent>
        <artifactId>org.argeo.ext.equinox.jetty</artifactId>
        <name>Extension of Equinox Jetty Integration</name>
+       <dependencies>
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.cms</artifactId>
+                       <version>2.1.77-SNAPSHOT</version>
+               </dependency>
+       </dependencies>
 </project>
\ No newline at end of file
index e59bbc0121e7833441864a2db840e1722d034452..83934537c364a99e08d6304d35d4244e03d53b08 100644 (file)
@@ -1,21 +1,29 @@
 package org.argeo.equinox.jetty;
 
 import java.net.HttpCookie;
+import java.util.Collection;
 import java.util.Dictionary;
 import java.util.List;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpSession;
 
+import org.argeo.cms.auth.CmsSession;
 import org.eclipse.equinox.http.jetty.JettyCustomizer;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.websocket.api.UpgradeRequest;
+import org.eclipse.jetty.websocket.api.UpgradeResponse;
 import org.eclipse.jetty.websocket.common.WebSocketSession;
 import org.eclipse.jetty.websocket.common.WebSocketSessionListener;
+import org.eclipse.jetty.websocket.jsr356.JsrSession;
 import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
 import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.useradmin.Authorization;
 
 public class WebSocketJettyCustomizer extends JettyCustomizer {
        private BundleContext bc = FrameworkUtil.getBundle(WebSocketJettyCustomizer.class).getBundleContext();
@@ -24,6 +32,38 @@ public class WebSocketJettyCustomizer extends JettyCustomizer {
        public Object customizeContext(Object context, Dictionary<String, ?> settings) {
                ServletContextHandler servletContextHandler = (ServletContextHandler) context;
                new WebSocketInit(servletContextHandler).start();
+//             servletContextHandler.addFilter(new FilterHolder(new Filter() {
+//
+//                     @Override
+//                     public void init(FilterConfig filterConfig) throws ServletException {
+//                             // TODO Auto-generated method stub
+//
+//                     }
+//
+//                     @Override
+//                     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+//                                     throws IOException, ServletException {
+//                             HttpServletRequest httpRequest = (HttpServletRequest) request;
+//                             HttpServletResponse httpResponse = (HttpServletResponse) response;
+//
+//                             HttpRequestCallbackHandler callbackHandler = new HttpRequestCallbackHandler(httpRequest, httpResponse);
+//                             try {
+//                                     LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, callbackHandler);
+//                                     lc.login();
+//
+//                                     chain.doFilter(httpRequest, httpResponse);
+//                             } catch (LoginException e) {
+//                                     httpResponse.setStatus(403);
+//                             }
+//
+//                     }
+//
+//                     @Override
+//                     public void destroy() {
+//                             // TODO Auto-generated method stub
+//
+//                     }
+//             }), "/vje/events", EnumSet.of(DispatcherType.REQUEST));
                return super.customizeContext(context, settings);
        }
 
@@ -41,23 +81,69 @@ public class WebSocketJettyCustomizer extends JettyCustomizer {
                        ServerContainer serverContainer;
                        try {
                                serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
-//                             serverContainer.addSessionListener(new WebSocketSessionListener() {
-//
-//                                     @Override
-//                                     public void onSessionOpened(WebSocketSession session) {
-//                                             UpgradeRequest upgradeRequest = session.getUpgradeRequest();
-//                                             List<HttpCookie> cookies = upgradeRequest.getCookies();
-//                                             System.out.println("Upgrade request cookies : " + cookies);
-//                                             HttpSession httpSession = (HttpSession) upgradeRequest.getSession();
-//                                             System.out.println("Upgrade request session ID : " + httpSession.getId());
-//                                     }
-//
-//                                     @Override
-//                                     public void onSessionClosed(WebSocketSession session) {
-//                                             // TODO Auto-generated method stub
-//
-//                                     }
-//                             });
+                               serverContainer.addSessionListener(new WebSocketSessionListener() {
+
+                                       @Override
+                                       public void onSessionOpened(WebSocketSession session) {
+                                               UpgradeRequest upgradeRequest = session.getUpgradeRequest();
+                                               UpgradeResponse upgradeResponse = session.getUpgradeResponse();
+                                               List<HttpCookie> cookies = upgradeRequest.getCookies();
+
+                                               System.out.println("Upgrade request cookies : " + cookies);
+                                               String httpSessionId = null;
+                                               if (cookies != null) {
+                                                       for (HttpCookie cookie : cookies) {
+                                                               if (cookie.getName().equals("JSESSIONID")) {
+                                                                       httpSessionId = cookie.getValue();
+                                                               }
+                                                       }
+                                               }
+
+                                               if (httpSessionId == null) {
+                                                       HttpSession httpSession = (HttpSession) upgradeRequest.getSession();
+                                                       if (httpSession == null) {
+//                                                     session.disconnect();
+//                                                     return;
+                                                       } else {
+                                                               httpSessionId = httpSession.getId();
+                                                               System.out.println("Upgrade request session ID : " + httpSession.getId());
+                                                       }
+                                               }
+
+                                               if (httpSessionId != null) {
+                                                       int dotIdx = httpSessionId.lastIndexOf('.');
+                                                       if (dotIdx > 0) {
+                                                               httpSessionId = httpSessionId.substring(0, dotIdx);
+                                                       }
+                                               }
+
+                                               CmsSession cmsSession = getCmsSession(httpSessionId);
+                                               if (cmsSession == null) {
+                                                       session.disconnect();
+                                                       return;
+//                                                     try {
+//                                                             session.getUpgradeResponse().sendForbidden("Web Sockets must always be authenticated.");
+//                                                     } catch (IOException e) {
+//                                                             e.printStackTrace();
+//                                                     }
+                                               } else {
+                                                       JsrSession jsrSession = (JsrSession) session;
+                                                       String jsrId = jsrSession.getId();
+                                                       System.out.println("JSR ID: " + jsrId);
+                                                       jsrSession.getUserProperties().put(CmsSession.SESSION_LOCAL_ID, cmsSession.getLocalId());
+                                                       jsrSession.getUserProperties().put(CmsSession.SESSION_UUID, cmsSession.getUuid());
+                                                       jsrSession.getUserProperties().put(HttpContext.REMOTE_USER, cmsSession.getUserDn());
+                                                       // httpSession.setAttribute(HttpContext.AUTHORIZATION,
+                                                       // cmsSession.getAuthorization());
+                                               }
+                                       }
+
+                                       @Override
+                                       public void onSessionClosed(WebSocketSession session) {
+                                               // TODO Auto-generated method stub
+
+                                       }
+                               });
                        } catch (ServletException e) {
                                throw new IllegalStateException("Cannot configure web sockets", e);
                        }
@@ -85,4 +171,26 @@ public class WebSocketJettyCustomizer extends JettyCustomizer {
 
        }
 
+       private CmsSession getCmsSession(String httpSessionId) {
+               if (httpSessionId == null)
+                       return null;
+
+               Collection<ServiceReference<CmsSession>> sr;
+               try {
+                       sr = bc.getServiceReferences(CmsSession.class,
+                                       "(" + CmsSession.SESSION_LOCAL_ID + "=" + httpSessionId + ")");
+               } catch (InvalidSyntaxException e) {
+                       throw new IllegalStateException("Cannot get CMS session for id " + httpSessionId, e);
+               }
+               if (sr.size() == 1) {
+                       CmsSession cmsSession = bc.getService(sr.iterator().next());
+                       Authorization authorization = cmsSession.getAuthorization();
+                       if (authorization.getName() == null)
+                               return null;// anonymous is not sufficient
+                       return cmsSession;
+               } else {
+                       return null;
+               }
+       }
+
 }