]> source.dussan.org Git - archiva.git/blob
ae862206e3066fc78a3362bb41bbca7806e70892
[archiva.git] /
1 package org.codehaus.plexus.redback.struts2.interceptor;
2
3 /*
4  * Copyright 2005-2006 The Codehaus.
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
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;
38
39 import javax.inject.Inject;
40 import javax.servlet.http.HttpSession;
41
42 /**
43  * AutoLoginInterceptor
44  *
45  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
46  */
47 @Controller( "redbackAutoLoginInterceptor" )
48 @Scope( "prototype" )
49 public class AutoLoginInterceptor
50     implements Interceptor
51 {
52     private Logger log = LoggerFactory.getLogger( AutoLoginInterceptor.class );
53
54     static final String PASSWORD_CHANGE = "security-must-change-password";
55
56     static final String ACCOUNT_LOCKED = "security-login-locked";
57
58     /**
59      *
60      */
61     @Inject
62     private SecuritySystem securitySystem;
63
64     /**
65      *
66      */
67     @Inject
68     private AutoLoginCookies autologinCookies;
69
70     public void destroy()
71     {
72         // Ignore
73     }
74
75     public void init()
76     {
77         // Ignore
78     }
79
80     /**
81      * @noinspection ProhibitedExceptionDeclared
82      */
83     public String intercept( ActionInvocation invocation )
84         throws Exception
85     {
86         SecuritySession securitySession = getSecuritySession();
87
88         if ( securitySession != null && securitySession.isAuthenticated() )
89         {
90             // User already authenticated.
91             log.debug( "User already authenticated." );
92
93             if ( !checkCookieConsistency( securitySession ) )
94             {
95                 // update single sign on cookie
96                 autologinCookies.setSignonCookie( securitySession.getUser().getUsername(),
97                                                   ServletActionContext.getResponse(),
98                                                   ServletActionContext.getRequest() );
99             }
100         }
101         else
102         {
103             AuthenticationKey authkey =
104                 autologinCookies.getSignonKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
105
106             if ( authkey != null )
107             {
108                 try
109                 {
110                     securitySession = checkAuthentication( authkey, invocation.getInvocationContext().getName().equals(
111                         PASSWORD_CHANGE ) );
112
113                     if ( securitySession != null && securitySession.isAuthenticated() )
114                     {
115                         ActionContext.getContext().getSession().put( SecuritySystemConstants.SECURITY_SESSION_KEY,
116                                                                      securitySession );
117                         checkCookieConsistency( securitySession );
118                     }
119                     else
120                     {
121                         autologinCookies.removeSignonCookie( ServletActionContext.getResponse(),
122                                                              ServletActionContext.getRequest() );
123                         autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
124                                                                  ServletActionContext.getRequest() );
125                     }
126                 }
127                 catch ( AccountLockedException e )
128                 {
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;
135                 }
136                 catch ( MustChangePasswordException e )
137                 {
138                     return PASSWORD_CHANGE;
139                 }
140             }
141             else if ( autologinCookies.isRememberMeEnabled() )
142             {
143                 authkey = autologinCookies.getRememberMeKey( ServletActionContext.getResponse(),
144                                                              ServletActionContext.getRequest() );
145
146                 if ( authkey != null )
147                 {
148                     try
149                     {
150                         securitySession = checkAuthentication( authkey, false );
151
152                         if ( securitySession == null || !securitySession.isAuthenticated() )
153                         {
154                             autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
155                                                                      ServletActionContext.getRequest() );
156                         }
157                     }
158                     catch ( AccountLockedException e )
159                     {
160                         log.info( "Account Locked : Username [{}]", e.getUser().getUsername(), e );
161                         autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
162                                                                  ServletActionContext.getRequest() );
163                         return ACCOUNT_LOCKED;
164                     }
165                     catch ( MustChangePasswordException e )
166                     {
167                         return PASSWORD_CHANGE;
168                     }
169                 }
170             }
171         }
172
173         return invocation.invoke();
174     }
175
176     private boolean checkCookieConsistency( SecuritySession securitySession )
177     {
178         String username = securitySession.getUser().getUsername();
179
180         boolean failed = false;
181
182         AuthenticationKey key =
183             autologinCookies.getRememberMeKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
184         if ( key != null )
185         {
186             if ( !key.getForPrincipal().equals( username ) )
187             {
188                 log.debug( "Login invalidated: remember me cookie was for{}; but session was for {}",
189                            key.getForPrincipal(), username );
190                 failed = true;
191             }
192         }
193
194         if ( !failed )
195         {
196             key =
197                 autologinCookies.getSignonKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
198             if ( key != null )
199             {
200                 if ( !key.getForPrincipal().equals( username ) )
201                 {
202                     log.debug( "Login invalidated: signon cookie was for {}; but session was for {}",
203                                key.getForPrincipal(), username );
204                     failed = true;
205                 }
206             }
207             else
208             {
209                 log.debug( "Login invalidated: signon cookie was removed" );
210                 failed = true;
211             }
212         }
213
214         if ( failed )
215         {
216             removeCookiesAndSession();
217         }
218
219         return failed;
220     }
221
222     private SecuritySession checkAuthentication( AuthenticationKey authkey, boolean enforcePasswordChange )
223         throws AccountLockedException, MustChangePasswordException
224     {
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 );
231
232         try
233         {
234             securitySession = securitySystem.authenticate( authsource );
235
236             if ( securitySession.isAuthenticated() )
237             {
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." );
240
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 );
244
245                 autologinCookies.setSignonCookie( authkey.getForPrincipal(), ServletActionContext.getResponse(),
246                                                   ServletActionContext.getRequest() );
247             }
248             else
249             {
250                 AuthenticationResult result = securitySession.getAuthenticationResult();
251                 log.info( "Login interceptor failed against principal : {}", result.getPrincipal(),
252                           result.getException() );
253             }
254
255         }
256         catch ( AuthenticationException e )
257         {
258             log.info( "Authentication Exception.", e );
259         }
260         catch ( UserNotFoundException e )
261         {
262             log.info( "User Not Found: {}", authkey.getForPrincipal(), e );
263         }
264         return securitySession;
265     }
266
267     private void removeCookiesAndSession()
268     {
269         autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
270                                                  ServletActionContext.getRequest() );
271         autologinCookies.removeSignonCookie( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
272
273         HttpSession session = ServletActionContext.getRequest().getSession();
274         if ( session != null )
275         {
276             session.removeAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY );
277         }
278     }
279
280     private SecuritySession getSecuritySession()
281     {
282         HttpSession session = ServletActionContext.getRequest().getSession();
283         if ( session == null )
284         {
285             log.debug( "No HTTP Session exists." );
286             return null;
287         }
288
289         SecuritySession secSession =
290             (SecuritySession) session.getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY );
291         log.debug( "Returning Security Session: {}", secSession );
292         return secSession;
293     }
294 }