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 private final static Log log
= LogFactory
.getLog(AbstractLoginModule
.class);
51 private CallbackHandler callbackHandler
;
52 private Subject subject
;
54 private Authentication authentication
;
57 private BundleContext bundleContext
;
58 private ServiceReference
<AuthenticationManager
> authenticationManager
;
60 protected abstract Authentication
processLogin(
61 CallbackHandler callbackHandler
) throws LoginException
,
62 UnsupportedCallbackException
, IOException
, InterruptedException
;
65 public void initialize(Subject subject
, CallbackHandler callbackHandler
,
66 Map
<String
, ?
> sharedState
, Map
<String
, ?
> options
) {
67 this.callbackHandler
= callbackHandler
;
68 this.subject
= subject
;
69 this.bundleContext
= Activator
.getBundleContext();
70 this.authenticationManager
= bundleContext
71 .getServiceReference(AuthenticationManager
.class);
75 public boolean login() throws LoginException
{
77 Authentication currentAuth
= SecurityContextHolder
.getContext()
80 if (currentAuth
== null && Display
.getCurrent() != null) {
81 // try to load authentication from session
82 HttpServletRequest httpRequest
= RWT
.getRequest();
83 HttpSession httpSession
= httpRequest
.getSession();
84 // log.debug(httpSession.getId());
85 Object contextFromSessionObject
= httpSession
86 .getAttribute(SPRING_SECURITY_CONTEXT_KEY
);
87 if (contextFromSessionObject
!= null) {
88 currentAuth
= (Authentication
) contextFromSessionObject
;
89 SecurityContextHolder
.getContext().setAuthentication(
94 // thread already logged in
95 if (currentAuth
!= null) {
96 if (subject
.getPrincipals(Authentication
.class).size() == 0) {
97 // throw new LoginException(
98 // "Security context set but not Authentication principal");
100 Authentication principal
= subject
101 .getPrincipals(Authentication
.class).iterator()
103 if (principal
!= currentAuth
)
104 throw new LoginException(
105 "Already authenticated with a different auth");
110 // if (callbackHandler == null)
111 // throw new LoginException("No callback handler available");
113 authentication
= processLogin(callbackHandler
);
114 if (authentication
!= null) {
116 // SET THE AUTHENTICATION
118 SecurityContext securityContext
= SecurityContextHolder
120 securityContext
.setAuthentication(authentication
);
121 if (Display
.getCurrent() != null) {
122 HttpServletRequest httpRequest
= RWT
.getRequest();
123 HttpSession httpSession
= httpRequest
.getSession();
124 if (httpSession
.getAttribute(SPRING_SECURITY_CONTEXT_KEY
) == null)
125 httpSession
.setAttribute(SPRING_SECURITY_CONTEXT_KEY
,
130 throw new LoginException("No authentication returned");
132 } catch (LoginException e
) {
134 } catch (ThreadDeath e
) {
135 LoginException le
= new LoginException(
136 "Spring Security login thread died");
139 } catch (Exception e
) {
140 LoginException le
= new LoginException(
141 "Spring Security login failed");
148 public boolean logout() throws LoginException
{
149 SecurityContextHolder
.getContext().setAuthentication(null);
150 if (Display
.getCurrent() != null) {
151 HttpServletRequest httpRequest
= RWT
.getRequest();
152 HttpSession httpSession
= httpRequest
.getSession();
153 if (httpSession
.getAttribute(SPRING_SECURITY_CONTEXT_KEY
) != null)
154 httpSession
.setAttribute(SPRING_SECURITY_CONTEXT_KEY
, null);
160 public boolean commit() throws LoginException
{
165 public boolean abort() throws LoginException
{
166 SecurityContextHolder
.getContext().setAuthentication(null);
171 * Return the related {@link BundleContext} (never null), or throws an
172 * Exception if the login module was not properly initialised.
174 protected BundleContext
getBundleContext() {
175 if (bundleContext
== null)
176 throw new ArgeoException("No bundle context provided");
177 return bundleContext
;
180 AuthenticationManager
getAuthenticationManager() {
181 BundleContext bc
= getBundleContext();
182 assert authenticationManager
!= null;
183 return bc
.getService(authenticationManager
);
186 protected Subject
getSubject() {