1 package org.codehaus.plexus.redback.struts2.interceptor;
4 * Copyright 2005-2006 The Codehaus.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 import com.opensymphony.xwork2.ActionContext;
20 import com.opensymphony.xwork2.ActionInvocation;
21 import com.opensymphony.xwork2.interceptor.Interceptor;
22 import org.apache.struts2.ServletActionContext;
23 import org.codehaus.plexus.redback.authentication.AuthenticationException;
24 import org.codehaus.plexus.redback.authentication.AuthenticationResult;
25 import org.codehaus.plexus.redback.authentication.TokenBasedAuthenticationDataSource;
26 import org.codehaus.plexus.redback.keys.AuthenticationKey;
27 import org.codehaus.plexus.redback.policy.AccountLockedException;
28 import org.codehaus.plexus.redback.policy.MustChangePasswordException;
29 import org.codehaus.plexus.redback.system.SecuritySession;
30 import org.codehaus.plexus.redback.system.SecuritySystem;
31 import org.codehaus.plexus.redback.system.SecuritySystemConstants;
32 import org.codehaus.plexus.redback.users.UserNotFoundException;
33 import org.codehaus.redback.integration.util.AutoLoginCookies;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.springframework.context.annotation.Scope;
37 import org.springframework.stereotype.Controller;
39 import javax.inject.Inject;
40 import javax.servlet.http.HttpSession;
43 * AutoLoginInterceptor
45 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
47 @Controller( "redbackAutoLoginInterceptor" )
49 public class AutoLoginInterceptor
50 implements Interceptor
52 private Logger log = LoggerFactory.getLogger( AutoLoginInterceptor.class );
54 static final String PASSWORD_CHANGE = "security-must-change-password";
56 static final String ACCOUNT_LOCKED = "security-login-locked";
62 private SecuritySystem securitySystem;
68 private AutoLoginCookies autologinCookies;
81 * @noinspection ProhibitedExceptionDeclared
83 public String intercept( ActionInvocation invocation )
86 SecuritySession securitySession = getSecuritySession();
88 if ( securitySession != null && securitySession.isAuthenticated() )
90 // User already authenticated.
91 log.debug( "User already authenticated." );
93 if ( !checkCookieConsistency( securitySession ) )
95 // update single sign on cookie
96 autologinCookies.setSignonCookie( securitySession.getUser().getUsername(),
97 ServletActionContext.getResponse(),
98 ServletActionContext.getRequest() );
103 AuthenticationKey authkey =
104 autologinCookies.getSignonKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
106 if ( authkey != null )
110 securitySession = checkAuthentication( authkey, invocation.getInvocationContext().getName().equals(
113 if ( securitySession != null && securitySession.isAuthenticated() )
115 ActionContext.getContext().getSession().put( SecuritySystemConstants.SECURITY_SESSION_KEY,
117 checkCookieConsistency( securitySession );
121 autologinCookies.removeSignonCookie( ServletActionContext.getResponse(),
122 ServletActionContext.getRequest() );
123 autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
124 ServletActionContext.getRequest() );
127 catch ( AccountLockedException e )
129 log.info( "Account Locked : Username [{}]", e.getUser().getUsername(), e );
130 autologinCookies.removeSignonCookie( ServletActionContext.getResponse(),
131 ServletActionContext.getRequest() );
132 autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
133 ServletActionContext.getRequest() );
134 return ACCOUNT_LOCKED;
136 catch ( MustChangePasswordException e )
138 return PASSWORD_CHANGE;
141 else if ( autologinCookies.isRememberMeEnabled() )
143 authkey = autologinCookies.getRememberMeKey( ServletActionContext.getResponse(),
144 ServletActionContext.getRequest() );
146 if ( authkey != null )
150 securitySession = checkAuthentication( authkey, false );
152 if ( securitySession == null || !securitySession.isAuthenticated() )
154 autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
155 ServletActionContext.getRequest() );
158 catch ( AccountLockedException e )
160 log.info( "Account Locked : Username [{}]", e.getUser().getUsername(), e );
161 autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
162 ServletActionContext.getRequest() );
163 return ACCOUNT_LOCKED;
165 catch ( MustChangePasswordException e )
167 return PASSWORD_CHANGE;
173 return invocation.invoke();
176 private boolean checkCookieConsistency( SecuritySession securitySession )
178 String username = securitySession.getUser().getUsername();
180 boolean failed = false;
182 AuthenticationKey key =
183 autologinCookies.getRememberMeKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
186 if ( !key.getForPrincipal().equals( username ) )
188 log.debug( "Login invalidated: remember me cookie was for{}; but session was for {}",
189 key.getForPrincipal(), username );
197 autologinCookies.getSignonKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
200 if ( !key.getForPrincipal().equals( username ) )
202 log.debug( "Login invalidated: signon cookie was for {}; but session was for {}",
203 key.getForPrincipal(), username );
209 log.debug( "Login invalidated: signon cookie was removed" );
216 removeCookiesAndSession();
222 private SecuritySession checkAuthentication( AuthenticationKey authkey, boolean enforcePasswordChange )
223 throws AccountLockedException, MustChangePasswordException
225 SecuritySession securitySession = null;
226 log.debug( "Logging in with an authentication key: {}", authkey.getForPrincipal() );
227 TokenBasedAuthenticationDataSource authsource = new TokenBasedAuthenticationDataSource();
228 authsource.setPrincipal( authkey.getForPrincipal() );
229 authsource.setToken( authkey.getKey() );
230 authsource.setEnforcePasswordChange( enforcePasswordChange );
234 securitySession = securitySystem.authenticate( authsource );
236 if ( securitySession.isAuthenticated() )
238 // TODO: this should not happen if there is a password change required - but the password change action needs to log the user in on success to swap them
239 log.debug( "Login success." );
241 HttpSession session = ServletActionContext.getRequest().getSession( true );
242 session.setAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY, securitySession );
243 log.debug( "Setting session:{} to {}", SecuritySystemConstants.SECURITY_SESSION_KEY, securitySession );
245 autologinCookies.setSignonCookie( authkey.getForPrincipal(), ServletActionContext.getResponse(),
246 ServletActionContext.getRequest() );
250 AuthenticationResult result = securitySession.getAuthenticationResult();
251 log.info( "Login interceptor failed against principal : {}", result.getPrincipal(),
252 result.getException() );
256 catch ( AuthenticationException e )
258 log.info( "Authentication Exception.", e );
260 catch ( UserNotFoundException e )
262 log.info( "User Not Found: {}", authkey.getForPrincipal(), e );
264 return securitySession;
267 private void removeCookiesAndSession()
269 autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
270 ServletActionContext.getRequest() );
271 autologinCookies.removeSignonCookie( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
273 HttpSession session = ServletActionContext.getRequest().getSession();
274 if ( session != null )
276 session.removeAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY );
280 private SecuritySession getSecuritySession()
282 HttpSession session = ServletActionContext.getRequest().getSession();
283 if ( session == null )
285 log.debug( "No HTTP Session exists." );
289 SecuritySession secSession =
290 (SecuritySession) session.getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY );
291 log.debug( "Returning Security Session: {}", secSession );