KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > core > actions > AuthenticatedAction


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.sslexplorer.core.actions;
21
22 import java.io.IOException JavaDoc;
23
24 import javax.servlet.ServletException JavaDoc;
25 import javax.servlet.http.HttpServletRequest JavaDoc;
26 import javax.servlet.http.HttpServletResponse JavaDoc;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.struts.Globals;
31 import org.apache.struts.action.ActionForm;
32 import org.apache.struts.action.ActionForward;
33 import org.apache.struts.action.ActionMapping;
34 import org.apache.struts.action.ActionMessage;
35 import org.apache.struts.action.ActionMessages;
36
37 import com.sslexplorer.boot.Util;
38 import com.sslexplorer.core.CoreUtil;
39 import com.sslexplorer.core.ServletRequestAdapter;
40 import com.sslexplorer.core.ServletResponseAdapter;
41 import com.sslexplorer.policyframework.NoPermissionException;
42 import com.sslexplorer.policyframework.Permission;
43 import com.sslexplorer.policyframework.PolicyDatabaseFactory;
44 import com.sslexplorer.policyframework.ResourceType;
45 import com.sslexplorer.properties.PropertyProfile;
46 import com.sslexplorer.security.Constants;
47 import com.sslexplorer.security.LogonController;
48 import com.sslexplorer.security.LogonControllerFactory;
49 import com.sslexplorer.security.SessionInfo;
50 import com.sslexplorer.security.SystemDatabaseFactory;
51 import com.sslexplorer.security.User;
52
53 /**
54  *
55  * Generic action to be used for all authenticated actions by the SSL Explorer
56  * project. This checks that the user is logged on and if not directs them to
57  * the logon page. Once logon is complete, the user will be directed to the
58  * request path.
59  *
60  * @author Lee David Painter <lee@3sp.com>
61  * @author Brett Smith <brett@3sp.com>
62  * @since 0.1
63  * @see com.sslexplorer.core.actions.AuthenticatedDispatchAction
64  */

65 public abstract class AuthenticatedAction extends DefaultAction implements CoreAction {
66
67     static Log log = LogFactory.getLog(AuthenticatedAction.class);
68
69     // Private instance variables
70

71     private boolean requiresAdministrator;
72     private ResourceType resourceType;
73     private Permission[] permissions;
74
75     /**
76      * Use this constructor for actions that do not require any resource
77      * permissions
78      */

79     public AuthenticatedAction() {
80     }
81
82    
83     /**
84      * Use this constructor for actions that require a resource permission to
85      * operator
86      *
87      * @param resourceType resource type
88      * @param permissions permission required
89      */

90     public AuthenticatedAction(ResourceType resourceType, Permission permissions[]) {
91         if (resourceType == null || permissions == null || permissions.length < 1) {
92             throw new IllegalArgumentException JavaDoc("Must provide a resource type and at least 1 permission.");
93         }
94         this.resourceType = resourceType;
95         this.permissions = permissions;
96     }
97
98     /**
99      * Get the {@link SessionInfo} for this session. This will only be available
100      * after
101      * {@link #execute(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse)}
102      * has been called.
103      * <p>
104      * There are many places where the session info object is required. The
105      * usual way is to use
106      * {@link LogonController#getSessionInfo(HttpServletRequest)}. Whereever
107      * possible that method should be replaced with a call to this method.
108      *
109      * @param request TODO
110      *
111      * @return session info for request
112      */

113     public SessionInfo getSessionInfo(HttpServletRequest JavaDoc request) {
114         return LogonControllerFactory.getInstance().getSessionInfo(request);
115
116     }
117
118     public final ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest JavaDoc request,
119                                        HttpServletResponse JavaDoc response) throws Exception JavaDoc {
120         // Setup mode
121
boolean installMode = isInstallMode();
122         if (installMode) {
123             if ((getNavigationContext(mapping, form, request, response) & SessionInfo.SETUP_CONSOLE_CONTEXT) == 0) {
124                 return mapping.findForward("setup");
125             } else {
126                 /*
127                  * Make the mapping and form available, this helps with reusing
128                  * some JSP pages
129                  */

130                 request.setAttribute(Constants.REQ_ATTR_ACTION_MAPPING, mapping);
131                 request.setAttribute(Constants.REQ_ATTR_FORM, form);
132
133                 CoreUtil.checkNavigationContext(this, mapping, form, request, response);
134                 return onExecute(mapping, form, request, response);
135             }
136         }
137
138         try {
139             try {
140                 if (!SystemDatabaseFactory.getInstance().verifyIPAddress(request.getRemoteAddr())) {
141                     String JavaDoc link = null;
142                     log.error(request.getRemoteHost() + " is not authorized");
143                     if (log.isInfoEnabled())
144                         log.info("Logging off, IP address verification failed.");
145                     if(LogonControllerFactory.getInstance().hasClientLoggedOn(request, response) == LogonController.LOGGED_ON) {
146                         LogonControllerFactory.getInstance().logoffSession(request, response);
147                     }
148
149                     if (link != null) {
150                         return new ActionForward(link, true);
151                     } else {
152                         // Do not direct to logon page for Ajax requests
153
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
154                             response.setStatus(HttpServletResponse.SC_FORBIDDEN);
155                             return null;
156                         }
157                         return mapping.findForward("logon");
158                     }
159
160                 } else {
161
162                     int logonStatus = LogonControllerFactory.getInstance().hasClientLoggedOn(request, response);
163                     if (logonStatus == LogonController.INVALID_TICKET) {
164                         ActionMessages msgs = new ActionMessages();
165                         msgs.add(Globals.ERROR_KEY, new ActionMessage("login.invalidTicket"));
166                         saveErrors(request, msgs);
167                     } else if (logonStatus == LogonController.LOGGED_ON) {
168
169                         User currentUser = LogonControllerFactory.getInstance().getUser(request);
170
171                         // Set the logon ticket / domain logon ticket again
172
LogonControllerFactory.getInstance().addCookies(new ServletRequestAdapter(request),
173                             new ServletResponseAdapter(response),
174                             (String JavaDoc) request.getSession().getAttribute(Constants.LOGON_TICKET), getSessionInfo(request));
175
176                         if (!LogonControllerFactory.getInstance().isAdministrator(getSessionInfo(request).getUser())
177                                         && requiresAdministrator) {
178                             response.sendError(403, "You do not have permission to access this area");
179                             return null;
180                         } else {
181                             /*
182                              * Make the mapping and form available, this helps
183                              * with reusing some JSP pages
184                              */

185                             request.setAttribute(Constants.REQ_ATTR_ACTION_MAPPING, mapping);
186                             request.setAttribute(Constants.REQ_ATTR_FORM, form);
187
188                             // Check for intercepts, but don't forward if the
189
// result of an Ajax action
190

191                             ActionForward fwd = checkIntercept(mapping, request, response);
192                             if(fwd != null) {
193                                 return fwd;
194                             }
195
196                             /*
197                              * Make sure the current navigation context is
198                              * correct. If not, then check the user can switch
199                              * to the correct and switch it.
200                              */

201                             CoreUtil.checkNavigationContext(this, mapping, form, request, response);
202
203                             // Check the user has the permissions to access this
204
// page
205
if (resourceType != null) {
206                                 if (!PolicyDatabaseFactory.getInstance().isPermitted(resourceType, permissions, currentUser, false)) {
207                                     throw new NoPermissionException("Action denied for current user");
208                                 }
209                             }
210
211                             if (request.getSession().getAttribute(Constants.SESSION_LOCKED) == null || isIgnoreSessionLock()) {
212                                 if (requiresProfile()) {
213                                     PropertyProfile profile = (PropertyProfile) request.getSession().getAttribute(
214                                         Constants.SELECTED_PROFILE);
215                                     if (profile == null) {
216                                         request.getSession().setAttribute(Constants.ORIGINAL_REQUEST,
217                                             Util.getOriginalRequest(request));
218                                         return mapping.findForward("selectPropertyProfile");
219                                     }
220                                 }
221                                 return onExecute(mapping, form, request, response);
222                             }
223                         }
224                     }
225                 }
226             } catch (NoPermissionException e) {
227                 if (log.isDebugEnabled())
228                     log.debug("User attempted to access page they do have have permission for. Resource type = "
229                                     + resourceType
230                                     + ". Now attempting to find the first valid item in the current menu tree to display.", e);
231                 response.sendError(HttpServletResponse.SC_FORBIDDEN);
232                 return null;
233             } catch (SecurityException JavaDoc ex) {
234                 // Not logged in or expired
235
} catch (ServletException JavaDoc ex) {
236                 throw ex;
237             }
238
239             // Do not direct to logon page for Ajax requests
240
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
241                 response.setStatus(HttpServletResponse.SC_FORBIDDEN);
242                 return null;
243             }
244
245             return gotoLogon(mapping, form, request, response);
246         } catch (Throwable JavaDoc t) {
247             log.error("Failed to process authenticated request.", t);
248             throw t instanceof Exception JavaDoc ? (Exception JavaDoc) t : new Exception JavaDoc(t);
249         }
250     }
251
252     /**
253      * Logon is required. By default this will direct to the logon page.
254      * Subclasses may overide this method to go somewhere different.
255      *
256      * @param mapping mapping
257      * @param form form
258      * @param request request
259      * @param response response
260      * @return forward
261      * @throws Exception
262      */

263     protected ActionForward gotoLogon(ActionMapping mapping, ActionForm form, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws Exception JavaDoc {
264         request.getSession().setAttribute(Constants.ORIGINAL_REQUEST, Util.getOriginalRequest(request));
265         return mapping.findForward("logon");
266     }
267
268     /**
269      * Get the resource type that was passed in on the constructor. The resource
270      * type will be supplied if this particular action implementation deals with
271      * resources controlled by the policy framework. This is used to check
272      * permissions
273      *
274      * @return resource type
275      */

276     public ResourceType getResourceType() {
277         return resourceType;
278     }
279
280     /**
281      * Get if this action requires a profile to be selected. Some actions may
282      * not require a profile to be present (the main one being the profile
283      * selection page!). If no profile is found in the session and this method
284      * returned <code>true</code> then the user will be directed to the
285      * 'selectPropertyProfile' page.
286      *
287      * @return requires a profile
288      */

289
290     protected boolean requiresProfile() {
291         return true;
292     }
293
294     /**
295      * Get if this action requires authentication to operator.
296      *
297      * @return authentication
298      */

299     protected boolean requiresAuthentication() {
300         return true;
301     }
302
303     /**
304      * Get if this action should ignore any session locks
305      *
306      * @return ignore session locks
307      */

308     protected boolean isIgnoreSessionLock() {
309         return false;
310     }
311
312     /*
313      * Send SC_AUTHORIZED to the client browser forcing HTTP authentication with
314      * the realm "SSL-Explorer".
315      *
316      * @param response response to write authentication request to.
317      */

318     void sendAuthorizationError(HttpServletResponse JavaDoc response) throws IOException JavaDoc {
319         response.setHeader("WWW-Authenticate", "Basic realm=\"SSL-Explorer\"");
320         response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
321     }
322
323     /**
324      * This method is called when all the default checks have take place.
325      * Subclass would do their actual processing here.
326      *
327      * @param mapping mapping
328      * @param form form
329      * @param request request
330      * @param response response
331      * @return forward
332      * @throws Exception on any error
333      */

334     protected ActionForward onExecute(ActionMapping mapping, ActionForm form, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws Exception JavaDoc {
335         return mapping.findForward("success");
336     }
337
338     /**
339      * Return the navigation context this action may be used in as a mask. If
340      * the user is not in the appropriate navigation then they will be
341      * automatically redirected to the action that switches contexts.
342      *
343      * @param mapping mapping
344      * @param form form
345      * @param request request
346      * @param response response
347      * @return navigation context
348      * @see SessionInfo#MANAGEMENT_CONSOLE_CONTEXT
349      * @see SessionInfo#USER_CONSOLE_CONTEXT
350      * @see SessionInfo#getNavigationContext()
351      */

352     public abstract int getNavigationContext(ActionMapping mapping, ActionForm form, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response);
353     
354     protected void saveError(HttpServletRequest JavaDoc request, String JavaDoc message ) {
355         saveMessage(request, message, "");
356     }
357     
358     protected void saveError(HttpServletRequest JavaDoc request, String JavaDoc message, Object JavaDoc... objects) {
359         ActionMessages actionMessages = new ActionMessages();
360         actionMessages.add(Globals.ERROR_KEY, new ActionMessage(message, objects));
361         saveErrors(request, actionMessages);
362     }
363     
364     protected void saveMessage(HttpServletRequest JavaDoc request, String JavaDoc message ) {
365         saveMessage(request, message, "");
366     }
367
368     protected void saveMessage(HttpServletRequest JavaDoc request, String JavaDoc message, Object JavaDoc... objects) {
369         ActionMessages actionMessages = new ActionMessages();
370         actionMessages.add(Globals.MESSAGE_KEY, new ActionMessage(message, objects));
371         saveErrors(request, actionMessages);
372     }
373 }
Popular Tags