Rename packages in order to make future stable documentation clearer.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / websocket / CmsWebSocketConfigurator.java
index 7cfe5748b19a7af3c51bc452f05c53d84f7c6096..652f25298b0e3e4e2c7fd54f4f6353f1de975959 100644 (file)
@@ -1,10 +1,11 @@
 package org.argeo.cms.websocket;
 
-import java.util.ArrayList;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.List;
 
+import javax.security.auth.Subject;
 import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
 import javax.servlet.http.HttpSession;
 import javax.websocket.Extension;
 import javax.websocket.HandshakeResponse;
@@ -14,10 +15,14 @@ import javax.websocket.server.ServerEndpointConfig.Configurator;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.NodeConstants;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.argeo.node.NodeConstants;
+import org.osgi.service.http.context.ServletContextHelper;
 
+/** Customises the initialisation of a new web socket. */
 public class CmsWebSocketConfigurator extends Configurator {
+       public final static String WEBSOCKET_SUBJECT = "org.argeo.cms.websocket.subject";
+
        private final static Log log = LogFactory.getLog(CmsWebSocketConfigurator.class);
        final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
 
@@ -62,8 +67,7 @@ public class CmsWebSocketConfigurator extends Configurator {
                        log.debug("Web socket HTTP session id: " + httpSession.getId());
 
                if (httpSession == null) {
-                       rejectResponse(response);
-                       return;
+                       rejectResponse(response, null);
                }
                try {
                        LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
@@ -71,20 +75,29 @@ public class CmsWebSocketConfigurator extends Configurator {
                        lc.login();
                        if (log.isDebugEnabled())
                                log.debug("Web socket logged-in as " + lc.getSubject());
-                       sec.getUserProperties().put("subject", lc.getSubject());
-               } catch (LoginException e) {
-                       rejectResponse(response);
-                       return;
+                       Subject.doAs(lc.getSubject(), new PrivilegedAction<Void>() {
+
+                               @Override
+                               public Void run() {
+                                       sec.getUserProperties().put(ServletContextHelper.REMOTE_USER, AccessController.getContext());
+                                       return null;
+                               }
+
+                       });
+               } catch (Exception e) {
+                       rejectResponse(response, e);
                }
        }
 
-       protected void rejectResponse(HandshakeResponse response) {
-               List<String> lst = new ArrayList<String>();
-               lst.add("no");
-               response.getHeaders().put(HandshakeResponse.SEC_WEBSOCKET_ACCEPT, lst);
-
+       /**
+        * Behaviour when the web socket could not be authenticated. Throws an
+        * {@link IllegalStateException} by default.
+        * 
+        * @param e can be null
+        */
+       protected void rejectResponse(HandshakeResponse response, Exception e) {
                // violent implementation, as suggested in
                // https://stackoverflow.com/questions/21763829/jsr-356-how-to-abort-a-websocket-connection-during-the-handshake
-               // throw new IllegalStateException("Web socket cannot be authenticated");
+//             throw new IllegalStateException("Web socket cannot be authenticated");
        }
 }