]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.ee/src/org/argeo/cms/websocket/server/CmsWebSocketConfigurator.java
Add content type to package servlet
[lgpl/argeo-commons.git] / org.argeo.cms.ee / src / org / argeo / cms / websocket / server / CmsWebSocketConfigurator.java
1 package org.argeo.cms.websocket.server;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.security.auth.login.LoginContext;
7 import javax.security.auth.login.LoginException;
8 import javax.websocket.Extension;
9 import javax.websocket.HandshakeResponse;
10 import javax.websocket.server.HandshakeRequest;
11 import javax.websocket.server.ServerEndpointConfig;
12 import javax.websocket.server.ServerEndpointConfig.Configurator;
13
14 import org.argeo.api.cms.CmsAuth;
15 import org.argeo.api.cms.CmsLog;
16 import org.argeo.cms.auth.RemoteAuthCallbackHandler;
17 import org.argeo.cms.auth.RemoteAuthRequest;
18 import org.argeo.cms.auth.RemoteAuthResponse;
19 import org.argeo.cms.auth.RemoteAuthSession;
20 import org.argeo.cms.auth.RemoteAuthUtils;
21 import org.argeo.cms.servlet.CmsServletContext;
22
23 /**
24 * <strong>Disabled until third party issues are solved.</strong>. Customises
25 * the initialisation of a new web socket.
26 */
27 public class CmsWebSocketConfigurator extends Configurator {
28
29 private final static CmsLog log = CmsLog.getLog(CmsWebSocketConfigurator.class);
30
31 private final String httpAuthRealm = "Argeo";
32
33 @Override
34 public boolean checkOrigin(String originHeaderValue) {
35 return true;
36 }
37
38 @Override
39 public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
40 try {
41 return endpointClass.getDeclaredConstructor().newInstance();
42 } catch (Exception e) {
43 throw new IllegalArgumentException("Cannot get endpoint instance", e);
44 }
45 }
46
47 @Override
48 public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) {
49 return requested;
50 }
51
52 @Override
53 public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) {
54 if ((requested == null) || (requested.size() == 0))
55 return "";
56 if ((supported == null) || (supported.isEmpty()))
57 return "";
58 for (String possible : requested) {
59 if (possible == null)
60 continue;
61 if (supported.contains(possible))
62 return possible;
63 }
64 return "";
65 }
66
67 @Override
68 public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
69 // if (true)
70 // return;
71
72 WebSocketHandshakeRequest remoteAuthRequest = new WebSocketHandshakeRequest(request);
73 WebSocketHandshakeResponse remoteAuthResponse = new WebSocketHandshakeResponse(response);
74 // RemoteAuthSession httpSession = new ServletHttpSession(
75 // (javax.servlet.http.HttpSession) request.getHttpSession());
76 RemoteAuthSession remoteAuthSession = remoteAuthRequest.getSession();
77 if (log.isDebugEnabled() && remoteAuthSession != null)
78 log.debug("Web socket HTTP session id: " + remoteAuthSession.getId());
79
80 // if (remoteAuthSession == null) {
81 // rejectResponse(response, null);
82 // }
83 ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
84 Thread.currentThread().setContextClassLoader(CmsServletContext.class.getClassLoader());
85 LoginContext lc;
86 try {
87 lc = CmsAuth.USER.newLoginContext(new RemoteAuthCallbackHandler(remoteAuthRequest, remoteAuthResponse));
88 lc.login();
89 } catch (LoginException e) {
90 if (authIsRequired(remoteAuthRequest, remoteAuthResponse)) {
91 int statusCode = RemoteAuthUtils.askForWwwAuth(remoteAuthRequest, remoteAuthResponse, httpAuthRealm,
92 true);
93 // remoteAuthResponse.setHeader("Status-Code", Integer.toString(statusCode));
94 return;
95 } else {
96 lc = RemoteAuthUtils.anonymousLogin(remoteAuthRequest, remoteAuthResponse);
97 }
98 if (lc == null) {
99 rejectResponse(response, e);
100 return;
101 }
102 } finally {
103 Thread.currentThread().setContextClassLoader(currentThreadContextClassLoader);
104 }
105
106 // Subject subject = lc.getSubject();
107 // Subject.doAs(subject, new PrivilegedAction<Void>() {
108 //
109 // @Override
110 // public Void run() {
111 // // TODO also set login context in order to log out ?
112 // RemoteAuthUtils.configureRequestSecurity(remoteAuthRequest);
113 // return null;
114 // }
115 //
116 // });
117 }
118
119 protected boolean authIsRequired(RemoteAuthRequest remoteAuthRequest, RemoteAuthResponse remoteAuthResponse) {
120 return true;
121 }
122
123 /**
124 * Behaviour when the web socket could not be authenticated. Throws an
125 * {@link IllegalStateException} by default.
126 *
127 * @param e can be null
128 */
129 protected void rejectResponse(HandshakeResponse response, Exception e) {
130 response.getHeaders().put(HandshakeResponse.SEC_WEBSOCKET_ACCEPT, new ArrayList<String>());
131 // violent implementation, as suggested in
132 // https://stackoverflow.com/questions/21763829/jsr-356-how-to-abort-a-websocket-connection-during-the-handshake
133 // throw new IllegalStateException("Web socket cannot be authenticated");
134 }
135 }