]> source.dussan.org Git - archiva.git/blob
c00a4e35a258f2fd5b0b8f32300642ec4c1ce053
[archiva.git] /
1 package org.apache.archiva.redback.struts2.interceptor;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import com.opensymphony.xwork2.ActionContext;
23 import com.opensymphony.xwork2.ActionInvocation;
24 import com.opensymphony.xwork2.interceptor.Interceptor;
25 import org.apache.archiva.redback.keys.AuthenticationKey;
26 import org.apache.archiva.redback.policy.AccountLockedException;
27 import org.apache.archiva.redback.policy.MustChangePasswordException;
28 import org.apache.struts2.ServletActionContext;
29 import org.apache.archiva.redback.authentication.AuthenticationException;
30 import org.apache.archiva.redback.authentication.AuthenticationResult;
31 import org.apache.archiva.redback.authentication.TokenBasedAuthenticationDataSource;
32 import org.apache.archiva.redback.system.SecuritySession;
33 import org.apache.archiva.redback.system.SecuritySystem;
34 import org.apache.archiva.redback.system.SecuritySystemConstants;
35 import org.apache.archiva.redback.users.UserNotFoundException;
36 import org.apache.archiva.redback.integration.util.AutoLoginCookies;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.springframework.context.annotation.Scope;
40 import org.springframework.stereotype.Controller;
41
42 import javax.inject.Inject;
43 import javax.servlet.http.HttpSession;
44
45 /**
46  * AutoLoginInterceptor
47  *
48  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
49  */
50 @Controller( "redbackAutoLoginInterceptor" )
51 @Scope( "prototype" )
52 public class AutoLoginInterceptor
53     implements Interceptor
54 {
55     private Logger log = LoggerFactory.getLogger( AutoLoginInterceptor.class );
56
57     static final String PASSWORD_CHANGE = "security-must-change-password";
58
59     static final String ACCOUNT_LOCKED = "security-login-locked";
60
61     /**
62      *
63      */
64     @Inject
65     private SecuritySystem securitySystem;
66
67     /**
68      *
69      */
70     @Inject
71     private AutoLoginCookies autologinCookies;
72
73     public void destroy()
74     {
75         // Ignore
76     }
77
78     public void init()
79     {
80         // Ignore
81     }
82
83     /**
84      * @noinspection ProhibitedExceptionDeclared
85      */
86     public String intercept( ActionInvocation invocation )
87         throws Exception
88     {
89         SecuritySession securitySession = getSecuritySession();
90
91         if ( securitySession != null && securitySession.isAuthenticated() )
92         {
93             // User already authenticated.
94             log.debug( "User already authenticated." );
95
96             if ( !checkCookieConsistency( securitySession ) )
97             {
98                 // update single sign on cookie
99                 autologinCookies.setSignonCookie( securitySession.getUser().getUsername(),
100                                                   ServletActionContext.getResponse(),
101                                                   ServletActionContext.getRequest() );
102             }
103         }
104         else
105         {
106             AuthenticationKey authkey =
107                 autologinCookies.getSignonKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
108
109             if ( authkey != null )
110             {
111                 try
112                 {
113                     securitySession = checkAuthentication( authkey, invocation.getInvocationContext().getName().equals(
114                         PASSWORD_CHANGE ) );
115
116                     if ( securitySession != null && securitySession.isAuthenticated() )
117                     {
118                         ActionContext.getContext().getSession().put( SecuritySystemConstants.SECURITY_SESSION_KEY,
119                                                                      securitySession );
120                         checkCookieConsistency( securitySession );
121                     }
122                     else
123                     {
124                         autologinCookies.removeSignonCookie( ServletActionContext.getResponse(),
125                                                              ServletActionContext.getRequest() );
126                         autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
127                                                                  ServletActionContext.getRequest() );
128                     }
129                 }
130                 catch ( AccountLockedException e )
131                 {
132                     log.info( "Account Locked : Username [{}]", e.getUser().getUsername(), e );
133                     autologinCookies.removeSignonCookie( ServletActionContext.getResponse(),
134                                                          ServletActionContext.getRequest() );
135                     autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
136                                                              ServletActionContext.getRequest() );
137                     return ACCOUNT_LOCKED;
138                 }
139                 catch ( MustChangePasswordException e )
140                 {
141                     return PASSWORD_CHANGE;
142                 }
143             }
144             else if ( autologinCookies.isRememberMeEnabled() )
145             {
146                 authkey = autologinCookies.getRememberMeKey( ServletActionContext.getResponse(),
147                                                              ServletActionContext.getRequest() );
148
149                 if ( authkey != null )
150                 {
151                     try
152                     {
153                         securitySession = checkAuthentication( authkey, false );
154
155                         if ( securitySession == null || !securitySession.isAuthenticated() )
156                         {
157                             autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
158                                                                      ServletActionContext.getRequest() );
159                         }
160                     }
161                     catch ( AccountLockedException e )
162                     {
163                         log.info( "Account Locked : Username [{}]", e.getUser().getUsername(), e );
164                         autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
165                                                                  ServletActionContext.getRequest() );
166                         return ACCOUNT_LOCKED;
167                     }
168                     catch ( MustChangePasswordException e )
169                     {
170                         return PASSWORD_CHANGE;
171                     }
172                 }
173             }
174         }
175
176         return invocation.invoke();
177     }
178
179     private boolean checkCookieConsistency( SecuritySession securitySession )
180     {
181         String username = securitySession.getUser().getUsername();
182
183         boolean failed = false;
184
185         AuthenticationKey key =
186             autologinCookies.getRememberMeKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
187         if ( key != null )
188         {
189             if ( !key.getForPrincipal().equals( username ) )
190             {
191                 log.debug( "Login invalidated: remember me cookie was for{}; but session was for {}",
192                            key.getForPrincipal(), username );
193                 failed = true;
194             }
195         }
196
197         if ( !failed )
198         {
199             key =
200                 autologinCookies.getSignonKey( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
201             if ( key != null )
202             {
203                 if ( !key.getForPrincipal().equals( username ) )
204                 {
205                     log.debug( "Login invalidated: signon cookie was for {}; but session was for {}",
206                                key.getForPrincipal(), username );
207                     failed = true;
208                 }
209             }
210             else
211             {
212                 log.debug( "Login invalidated: signon cookie was removed" );
213                 failed = true;
214             }
215         }
216
217         if ( failed )
218         {
219             removeCookiesAndSession();
220         }
221
222         return failed;
223     }
224
225     private SecuritySession checkAuthentication( AuthenticationKey authkey, boolean enforcePasswordChange )
226         throws AccountLockedException, MustChangePasswordException
227     {
228         SecuritySession securitySession = null;
229         log.debug( "Logging in with an authentication key: {}", authkey.getForPrincipal() );
230         TokenBasedAuthenticationDataSource authsource = new TokenBasedAuthenticationDataSource();
231         authsource.setPrincipal( authkey.getForPrincipal() );
232         authsource.setToken( authkey.getKey() );
233         authsource.setEnforcePasswordChange( enforcePasswordChange );
234
235         try
236         {
237             securitySession = securitySystem.authenticate( authsource );
238
239             if ( securitySession.isAuthenticated() )
240             {
241                 // 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
242                 log.debug( "Login success." );
243
244                 HttpSession session = ServletActionContext.getRequest().getSession( true );
245                 session.setAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY, securitySession );
246                 log.debug( "Setting session:{} to {}", SecuritySystemConstants.SECURITY_SESSION_KEY, securitySession );
247
248                 autologinCookies.setSignonCookie( authkey.getForPrincipal(), ServletActionContext.getResponse(),
249                                                   ServletActionContext.getRequest() );
250             }
251             else
252             {
253                 AuthenticationResult result = securitySession.getAuthenticationResult();
254                 log.info( "Login interceptor failed against principal : {}", result.getPrincipal(),
255                           result.getException() );
256             }
257
258         }
259         catch ( AuthenticationException e )
260         {
261             log.info( "Authentication Exception.", e );
262         }
263         catch ( UserNotFoundException e )
264         {
265             log.info( "User Not Found: {}", authkey.getForPrincipal(), e );
266         }
267         return securitySession;
268     }
269
270     private void removeCookiesAndSession()
271     {
272         autologinCookies.removeRememberMeCookie( ServletActionContext.getResponse(),
273                                                  ServletActionContext.getRequest() );
274         autologinCookies.removeSignonCookie( ServletActionContext.getResponse(), ServletActionContext.getRequest() );
275
276         HttpSession session = ServletActionContext.getRequest().getSession();
277         if ( session != null )
278         {
279             session.removeAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY );
280         }
281     }
282
283     private SecuritySession getSecuritySession()
284     {
285         HttpSession session = ServletActionContext.getRequest().getSession();
286         if ( session == null )
287         {
288             log.debug( "No HTTP Session exists." );
289             return null;
290         }
291
292         SecuritySession secSession =
293             (SecuritySession) session.getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY );
294         log.debug( "Returning Security Session: {}", secSession );
295         return secSession;
296     }
297 }