2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.cms
.internal
.auth
;
18 import java
.io
.IOException
;
21 import javax
.security
.auth
.Subject
;
22 import javax
.security
.auth
.callback
.CallbackHandler
;
23 import javax
.security
.auth
.callback
.UnsupportedCallbackException
;
24 import javax
.security
.auth
.login
.LoginException
;
25 import javax
.security
.auth
.spi
.LoginModule
;
26 import javax
.servlet
.http
.HttpServletRequest
;
27 import javax
.servlet
.http
.HttpSession
;
29 import org
.apache
.commons
.logging
.Log
;
30 import org
.apache
.commons
.logging
.LogFactory
;
31 import org
.argeo
.ArgeoException
;
32 import org
.argeo
.cms
.internal
.kernel
.Activator
;
33 import org
.eclipse
.rap
.rwt
.RWT
;
34 import org
.eclipse
.swt
.widgets
.Display
;
35 import org
.osgi
.framework
.BundleContext
;
36 import org
.osgi
.framework
.ServiceReference
;
37 import org
.springframework
.security
.authentication
.AuthenticationManager
;
38 import org
.springframework
.security
.core
.Authentication
;
39 import org
.springframework
.security
.core
.context
.SecurityContext
;
40 import org
.springframework
.security
.core
.context
.SecurityContextHolder
;
42 /** Login module which caches one subject per thread. */
43 public abstract class AbstractLoginModule
implements LoginModule
{
45 * From org.springframework.security.context.
46 * HttpSessionContextIntegrationFilter
48 private final static String SPRING_SECURITY_CONTEXT_KEY
= "SPRING_SECURITY_CONTEXT";
50 @SuppressWarnings("unused")
51 private final static Log log
= LogFactory
.getLog(AbstractLoginModule
.class);
52 private CallbackHandler callbackHandler
;
53 private Subject subject
;
55 private Authentication authentication
;
58 private BundleContext bundleContext
;
59 private ServiceReference
<AuthenticationManager
> authenticationManager
;
61 protected abstract Authentication
processLogin(
62 CallbackHandler callbackHandler
) throws LoginException
,
63 UnsupportedCallbackException
, IOException
, InterruptedException
;
66 public void initialize(Subject subject
, CallbackHandler callbackHandler
,
67 Map
<String
, ?
> sharedState
, Map
<String
, ?
> options
) {
68 this.callbackHandler
= callbackHandler
;
69 this.subject
= subject
;
70 this.bundleContext
= Activator
.getBundleContext();
71 this.authenticationManager
= bundleContext
72 .getServiceReference(AuthenticationManager
.class);
76 public boolean login() throws LoginException
{
78 Authentication currentAuth
= SecurityContextHolder
.getContext()
81 if (currentAuth
== null && Display
.getCurrent() != null) {
82 // try to load authentication from session
83 HttpServletRequest httpRequest
= RWT
.getRequest();
84 HttpSession httpSession
= httpRequest
.getSession();
85 // log.debug(httpSession.getId());
86 Object contextFromSessionObject
= httpSession
87 .getAttribute(SPRING_SECURITY_CONTEXT_KEY
);
88 if (contextFromSessionObject
!= null) {
89 currentAuth
= (Authentication
) contextFromSessionObject
;
90 SecurityContextHolder
.getContext().setAuthentication(
95 // thread already logged in
96 if (currentAuth
!= null) {
97 if (subject
.getPrincipals(Authentication
.class).size() == 0) {
98 // throw new LoginException(
99 // "Security context set but not Authentication principal");
101 Authentication principal
= subject
102 .getPrincipals(Authentication
.class).iterator()
104 if (principal
!= currentAuth
)
105 throw new LoginException(
106 "Already authenticated with a different auth");
111 // if (callbackHandler == null)
112 // throw new LoginException("No callback handler available");
114 authentication
= processLogin(callbackHandler
);
115 if (authentication
!= null) {
117 // SET THE AUTHENTICATION
119 SecurityContext securityContext
= SecurityContextHolder
121 securityContext
.setAuthentication(authentication
);
122 if (Display
.getCurrent() != null) {
123 HttpServletRequest httpRequest
= RWT
.getRequest();
124 HttpSession httpSession
= httpRequest
.getSession();
125 if (httpSession
.getAttribute(SPRING_SECURITY_CONTEXT_KEY
) == null)
126 httpSession
.setAttribute(SPRING_SECURITY_CONTEXT_KEY
,
131 throw new LoginException("No authentication returned");
133 } catch (LoginException e
) {
135 } catch (ThreadDeath e
) {
136 LoginException le
= new LoginException(
137 "Spring Security login thread died");
140 } catch (Exception e
) {
141 LoginException le
= new LoginException(
142 "Spring Security login failed");
149 public boolean logout() throws LoginException
{
150 SecurityContextHolder
.getContext().setAuthentication(null);
151 if (Display
.getCurrent() != null) {
152 HttpServletRequest httpRequest
= RWT
.getRequest();
153 HttpSession httpSession
= httpRequest
.getSession();
154 if (httpSession
.getAttribute(SPRING_SECURITY_CONTEXT_KEY
) != null)
155 httpSession
.setAttribute(SPRING_SECURITY_CONTEXT_KEY
, null);
161 public boolean commit() throws LoginException
{
166 public boolean abort() throws LoginException
{
167 SecurityContextHolder
.getContext().setAuthentication(null);
172 * Return the related {@link BundleContext} (never null), or throws an
173 * Exception if the login module was not properly initialised.
175 protected BundleContext
getBundleContext() {
176 if (bundleContext
== null)
177 throw new ArgeoException("No bundle context provided");
178 return bundleContext
;
181 AuthenticationManager
getAuthenticationManager() {
182 BundleContext bc
= getBundleContext();
183 assert authenticationManager
!= null;
184 return bc
.getService(authenticationManager
);
187 protected Subject
getSubject() {