]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/websocket/CmsWebSocketConfigurator.java
Set update policy to 'always' for SNAPSHOT repositories.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / websocket / CmsWebSocketConfigurator.java
1 package org.argeo.cms.websocket;
2
3 import java.util.List;
4
5 import javax.security.auth.login.LoginContext;
6 import javax.servlet.http.HttpSession;
7 import javax.websocket.Extension;
8 import javax.websocket.HandshakeResponse;
9 import javax.websocket.server.HandshakeRequest;
10 import javax.websocket.server.ServerEndpointConfig;
11 import javax.websocket.server.ServerEndpointConfig.Configurator;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.argeo.cms.auth.HttpRequestCallbackHandler;
16 import org.argeo.node.NodeConstants;
17
18 /** Customises the initialisation of a new web socket. */
19 public class CmsWebSocketConfigurator extends Configurator {
20 public final static String WEBSOCKET_SUBJECT = "org.argeo.cms.websocket.subject";
21
22 private final static Log log = LogFactory.getLog(CmsWebSocketConfigurator.class);
23 final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
24
25 @Override
26 public boolean checkOrigin(String originHeaderValue) {
27 return true;
28 }
29
30 @Override
31 public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
32 try {
33 return endpointClass.getDeclaredConstructor().newInstance();
34 } catch (Exception e) {
35 throw new IllegalArgumentException("Cannot get endpoint instance", e);
36 }
37 }
38
39 @Override
40 public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) {
41 return requested;
42 }
43
44 @Override
45 public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) {
46 if ((requested == null) || (requested.size() == 0))
47 return "";
48 if ((supported == null) || (supported.isEmpty()))
49 return "";
50 for (String possible : requested) {
51 if (possible == null)
52 continue;
53 if (supported.contains(possible))
54 return possible;
55 }
56 return "";
57 }
58
59 @Override
60 public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
61 HttpSession httpSession = (HttpSession) request.getHttpSession();
62 if (log.isDebugEnabled() && httpSession != null)
63 log.debug("Web socket HTTP session id: " + httpSession.getId());
64
65 if (httpSession == null) {
66 rejectResponse(response, null);
67 }
68 try {
69 LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
70 new HttpRequestCallbackHandler(httpSession));
71 lc.login();
72 if (log.isDebugEnabled())
73 log.debug("Web socket logged-in as " + lc.getSubject());
74 sec.getUserProperties().put(WEBSOCKET_SUBJECT, lc.getSubject());
75 } catch (Exception e) {
76 rejectResponse(response, e);
77 }
78 }
79
80 /**
81 * Behaviour when the web socket could not be authenticated. Throws an
82 * {@link IllegalStateException} by default.
83 *
84 * @param e can be null
85 */
86 protected void rejectResponse(HandshakeResponse response, Exception e) {
87 // violent implementation, as suggested in
88 // https://stackoverflow.com/questions/21763829/jsr-356-how-to-abort-a-websocket-connection-during-the-handshake
89 throw new IllegalStateException("Web socket cannot be authenticated");
90 }
91 }