1 package org.codehaus.plexus.redback.struts2.interceptor;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
22 import java.util.Calendar;
25 import javax.inject.Inject;
26 import javax.servlet.http.HttpServletRequest;
28 import org.apache.archiva.redback.configuration.UserConfiguration;
29 import org.apache.archiva.redback.users.UserManager;
30 import org.apache.struts2.ServletActionContext;
31 import org.apache.archiva.redback.policy.UserSecurityPolicy;
32 import org.apache.archiva.redback.system.DefaultSecuritySession;
33 import org.apache.archiva.redback.system.SecuritySession;
34 import org.apache.archiva.redback.system.SecuritySystem;
35 import org.apache.archiva.redback.system.SecuritySystemConstants;
36 import org.apache.archiva.redback.users.User;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 import com.opensymphony.xwork2.ActionContext;
41 import com.opensymphony.xwork2.ActionInvocation;
42 import com.opensymphony.xwork2.interceptor.Interceptor;
43 import org.springframework.context.annotation.Scope;
44 import org.springframework.stereotype.Controller;
47 * Interceptor to force the user to perform actions, when required.
49 * @author Edwin Punzalan
51 @Controller( "redbackPolicyEnforcementInterceptor" )
53 public class PolicyEnforcementInterceptor
54 implements Interceptor
56 private Logger log = LoggerFactory.getLogger( PolicyEnforcementInterceptor.class );
58 private static final String SECURITY_USER_MUST_CHANGE_PASSWORD = "security-must-change-password";
64 private UserConfiguration config;
70 protected SecuritySystem securitySystem;
83 * 1) validate that the user doesn't have to change their password, if they do then re-route accordingly
85 * @param actionInvocation
89 @SuppressWarnings("unchecked")
90 public String intercept( ActionInvocation actionInvocation )
94 if ( config.getBoolean( "security.policy.strict.enforcement.enabled" ) )
96 log.debug( "Enforcement: enforcing per click security policies." );
99 ActionContext context = ActionContext.getContext();
101 SecuritySession securitySession = null;
105 securitySession = (SecuritySession) context.getSession().get( SecuritySystemConstants.SECURITY_SESSION_KEY );
107 catch (IllegalStateException e)
109 log.debug("Could not get security session as the session was invalid", e);
112 UserSecurityPolicy policy = securitySystem.getPolicy();
114 if ( securitySession != null )
116 UserManager userManager = securitySystem.getUserManager();
117 User user = userManager.findUser( securitySession.getUser().getPrincipal() );
118 securitySession = new DefaultSecuritySession( securitySession.getAuthenticationResult(), user );
119 context.getSession().put( SecuritySystemConstants.SECURITY_SESSION_KEY, securitySession );
123 log.debug( "Enforcement: no user security session detected, skipping enforcement" );
124 return actionInvocation.invoke();
127 if ( checkForcePasswordChange( securitySession, actionInvocation ) )
129 Map<String, Object> session = ServletActionContext.getContext().getSession();
130 HttpServletRequest request = ServletActionContext.getRequest();
132 String queryString = request.getQueryString();
133 String targetUrl = request.getRequestURL() + ( queryString==null ? "" : "?" + queryString );
135 session.put( "targetUrl", targetUrl );
137 log.info( "storing targetUrl : {}", targetUrl );
139 return SECURITY_USER_MUST_CHANGE_PASSWORD;
142 if ( config.getBoolean( "security.policy.password.expiration.enabled" ) )
144 log.debug( "checking password expiration notification" );
146 UserManager userManager = securitySystem.getUserManager();
147 User user = userManager.findUser( securitySession.getUser().getPrincipal() );
149 Calendar expirationNotifyDate = Calendar.getInstance();
150 expirationNotifyDate.setTime( user.getLastPasswordChange() );
151 // add on the total days to expire minus the notification days
152 expirationNotifyDate.add( Calendar.DAY_OF_MONTH, policy.getPasswordExpirationDays() - config.getInt( "security.policy.password.expiration.notify.days" ) );
154 Calendar now = Calendar.getInstance();
156 if ( now.after( expirationNotifyDate ) )
158 log.debug( "setting password expiration notification" );
160 Calendar expirationDate = Calendar.getInstance();
161 expirationDate.setTime( user.getLastPasswordChange() );
162 expirationDate.add( Calendar.DAY_OF_MONTH, policy.getPasswordExpirationDays() );
163 Map<String, Object> session = ServletActionContext.getContext().getSession();
164 session.put( "passwordExpirationNotification", expirationDate.getTime().toString() );
168 return actionInvocation.invoke();
172 log.debug( "Enforcement: not processing per click security policies." );
173 return actionInvocation.invoke();
177 private boolean checkForcePasswordChange( SecuritySession securitySession, ActionInvocation actionInvocation )
180 * FIXME: something less 'hackish'
182 * these two classes should not be subject to this enforcement policy and this
183 * ideally should be governed by the interceptor stacks but that just didn't work
184 * when I was trying to solve the problem that way, psquad32 recommended I just
185 * find a way to get around this interceptor in the particular case I needed to and use
186 * "One stack to rule them all
188 if ( "org.codehaus.plexus.redback.struts2.action.PasswordAction".equals( actionInvocation.getAction().getClass().getName() ) )
190 log.debug( "Enforcement: skipping force password check on password action" );
194 if ( "org.codehaus.plexus.redback.struts2.action.LoginAction".equals( actionInvocation.getAction().getClass().getName() ) )
196 log.debug( "Enforcement: skipping force password check on login action" );
200 if ( "org.codehaus.plexus.redback.struts2.action.LogoutAction".equals( actionInvocation.getAction().getClass().getName() ) )
202 log.debug( "Enforcement: skipping force password check on logout action" );
206 if ( config.getBoolean( "security.policy.strict.force.password.change.enabled" ) )
208 log.debug( "Enforcement: checking active user password change enabled" );
210 if ( securitySession.getUser().isPasswordChangeRequired() )
212 log.info( "Enforcement: User must change password - forwarding to change password page." );
218 log.debug( "Enforcement: User doesn't need to change password." );