]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/auth/HttpLoginModule.java
Continue framework clean up.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / auth / HttpLoginModule.java
1 package org.argeo.cms.auth;
2
3 import java.io.IOException;
4 import java.util.Collection;
5 import java.util.Hashtable;
6 import java.util.Iterator;
7 import java.util.Map;
8
9 import javax.security.auth.Subject;
10 import javax.security.auth.callback.Callback;
11 import javax.security.auth.callback.CallbackHandler;
12 import javax.security.auth.callback.UnsupportedCallbackException;
13 import javax.security.auth.login.LoginException;
14 import javax.security.auth.spi.LoginModule;
15 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpSession;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.argeo.cms.CmsException;
21 import org.argeo.cms.internal.kernel.WebCmsSessionImpl;
22 import org.osgi.framework.BundleContext;
23 import org.osgi.framework.FrameworkUtil;
24 import org.osgi.framework.InvalidSyntaxException;
25 import org.osgi.framework.ServiceReference;
26 import org.osgi.framework.ServiceRegistration;
27 import org.osgi.service.http.HttpContext;
28 import org.osgi.service.useradmin.Authorization;
29
30 public class HttpLoginModule implements LoginModule, AuthConstants {
31 private final static Log log = LogFactory.getLog(HttpLoginModule.class);
32
33 private Subject subject = null;
34 private CallbackHandler callbackHandler = null;
35 private Map<String, Object> sharedState = null;
36
37 private HttpServletRequest request = null;
38
39 private BundleContext bc;
40
41 @SuppressWarnings("unchecked")
42 @Override
43 public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
44 Map<String, ?> options) {
45 bc = FrameworkUtil.getBundle(HttpLoginModule.class).getBundleContext();
46 assert bc != null;
47 this.subject = subject;
48 this.callbackHandler = callbackHandler;
49 this.sharedState = (Map<String, Object>) sharedState;
50 }
51
52 @Override
53 public boolean login() throws LoginException {
54 HttpRequestCallback httpCallback = new HttpRequestCallback();
55 try {
56 callbackHandler.handle(new Callback[] { httpCallback });
57 } catch (IOException e) {
58 throw new LoginException("Cannot handle http callback: " + e.getMessage());
59 } catch (UnsupportedCallbackException e) {
60 return false;
61 }
62 request = httpCallback.getRequest();
63 if (request == null)
64 return false;
65 Authorization authorization = checkHttp();
66 if (authorization == null)
67 return false;
68 sharedState.put(SHARED_STATE_AUTHORIZATION, authorization);
69 return true;
70 }
71
72 private Authorization checkHttp() {
73 Authorization authorization = null;
74 if (request != null) {
75 authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
76 if (authorization == null) {
77 String sessionId = request.getSession().getId();
78 authorization = (Authorization) request.getSession().getAttribute(HttpContext.AUTHORIZATION);
79 if (authorization == null) {
80 Collection<ServiceReference<WebCmsSession>> sr;
81 try {
82 sr = bc.getServiceReferences(WebCmsSession.class,
83 "(" + WebCmsSession.CMS_SESSION_ID + "=" + sessionId + ")");
84 } catch (InvalidSyntaxException e) {
85 throw new CmsException("Cannot get CMS session for id " + sessionId, e);
86 }
87 if (sr.size() == 1) {
88 WebCmsSession cmsSession = bc.getService(sr.iterator().next());
89 authorization = cmsSession.getAuthorization();
90 if (log.isTraceEnabled())
91 log.trace("Retrieved authorization from " + cmsSession);
92 }
93 }
94 }
95 }
96 return authorization;
97 }
98
99 @Override
100 public boolean commit() throws LoginException {
101 Authorization authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION);
102 if (authorization == null)
103 return false;
104 if (request == null)
105 return false;
106 String sessionId = request.getSession().getId();
107 if (authorization.getName() != null) {
108 request.setAttribute(HttpContext.REMOTE_USER, authorization.getName());
109 request.setAttribute(HttpContext.AUTHORIZATION, authorization);
110
111 HttpSession httpSession = request.getSession();
112 if (httpSession.getAttribute(HttpContext.AUTHORIZATION) == null) {
113
114 Collection<ServiceReference<WebCmsSession>> sr;
115 try {
116 sr = bc.getServiceReferences(WebCmsSession.class,
117 "(" + WebCmsSession.CMS_SESSION_ID + "=" + sessionId + ")");
118 } catch (InvalidSyntaxException e) {
119 throw new CmsException("Cannot get CMS session for id " + sessionId, e);
120 }
121 ServiceReference<WebCmsSession> cmsSessionRef;
122 if (sr.size() == 1) {
123 cmsSessionRef = sr.iterator().next();
124 } else if (sr.size() == 0) {
125 Hashtable<String, String> props = new Hashtable<>();
126 props.put(WebCmsSession.CMS_DN, authorization.getName());
127 props.put(WebCmsSession.CMS_SESSION_ID, sessionId);
128 WebCmsSessionImpl cmsSessionImpl = new WebCmsSessionImpl(sessionId, authorization);
129 ServiceRegistration<WebCmsSession> cmSessionReg = bc.registerService(WebCmsSession.class,
130 cmsSessionImpl, props);
131 cmsSessionImpl.setServiceRegistration(cmSessionReg);
132 cmsSessionRef = cmSessionReg.getReference();
133 if (log.isDebugEnabled())
134 log.debug("Initialized " + cmsSessionImpl + " for " + authorization.getName());
135 } else
136 throw new CmsException(sr.size() + " CMS sessions registered for " + sessionId);
137
138 WebCmsSession cmsSession = bc.getService(cmsSessionRef);
139 cmsSession.addHttpSession(request);
140 if (log.isTraceEnabled())
141 log.trace("Added " + request.getServletPath() + " to " + cmsSession + " (" + request.getRequestURI()
142 + ")");
143 httpSession.setAttribute(HttpContext.AUTHORIZATION, authorization);
144 }
145 }
146 if (subject.getPrivateCredentials(HttpSessionId.class).size() == 0)
147 subject.getPrivateCredentials().add(new HttpSessionId(sessionId));
148 else {
149 String storedSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
150 if (storedSessionId.equals(sessionId))
151 throw new LoginException(
152 "Subject already logged with session " + storedSessionId + " (not " + sessionId + ")");
153 }
154 return true;
155 }
156
157 @Override
158 public boolean abort() throws LoginException {
159 return false;
160 }
161
162 @Override
163 public boolean logout() throws LoginException {
164 String sessionId;
165 if (subject.getPrivateCredentials(HttpSessionId.class).size() == 1)
166 sessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
167 else
168 return false;
169 Collection<ServiceReference<WebCmsSession>> srs;
170 try {
171 srs = bc.getServiceReferences(WebCmsSession.class,
172 "(" + WebCmsSession.CMS_SESSION_ID + "=" + sessionId + ")");
173 } catch (InvalidSyntaxException e) {
174 throw new CmsException("Cannot retrieve CMS session #" + sessionId, e);
175 }
176
177 for (Iterator<ServiceReference<WebCmsSession>> it = srs.iterator(); it.hasNext();) {
178 ServiceReference<WebCmsSession> sr = it.next();
179 WebCmsSession cmsSession = bc.getService(sr);
180 cmsSession.cleanUp();
181 if (log.isDebugEnabled())
182 log.debug("Cleaned up " + cmsSession);
183 }
184 return true;
185 }
186
187 }