KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ivata > groupware > admin > security > struts > LoginAction


1 // Source file: h:/cvslocal/ivata groupware/src/com.ivata.groupware/admin/security/struts/LoginAction.java
2

3 /*
4  * Copyright (c) 2001 - 2005 ivata limited.
5  * All rights reserved.
6  * -----------------------------------------------------------------------------
7  * ivata groupware may be redistributed under the GNU General Public
8  * License as published by the Free Software Foundation;
9  * version 2 of the License.
10  *
11  * These programs are free software; you can redistribute them and/or
12  * modify them under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; version 2 of the License.
14  *
15  * These programs are distributed in the hope that they will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * See the GNU General Public License in the file LICENSE.txt for more
20  * details.
21  *
22  * If you would like a copy of the GNU General Public License write to
23  *
24  * Free Software Foundation, Inc.
25  * 59 Temple Place - Suite 330
26  * Boston, MA 02111-1307, USA.
27  *
28  *
29  * To arrange commercial support and licensing, contact ivata at
30  * http://www.ivata.com/contact.jsp
31  * -----------------------------------------------------------------------------
32  * $Log: LoginAction.java,v $
33  * Revision 1.5 2005/04/22 10:27:23 colinmacleod
34  * Changed to using hibernate properties
35  * rather than the hibernate configuration
36  * instance directly.
37  *
38  * Revision 1.4 2005/04/10 19:38:22 colinmacleod
39  * Updated login pages to change theme.
40  *
41  * Revision 1.3 2005/04/09 17:19:57 colinmacleod
42  * Changed copyright text to GPL v2 explicitly.
43  *
44  * Revision 1.2 2005/03/16 15:55:43 colinmacleod
45  * Changed debug logging for no java script to info.
46  *
47  * Revision 1.1.1.1 2005/03/10 17:51:40 colinmacleod
48  * Restructured ivata op around Hibernate/PicoContainer.
49  * Renamed ivata groupware.
50  *
51  * Revision 1.6 2004/12/31 18:27:44 colinmacleod
52  * Added MaskFactory to constructor of MaskAction.
53  *
54  * Revision 1.5 2004/12/23 20:50:58 colinmacleod
55  * Split off guest login from LoginAction into a new action.
56  *
57  * Revision 1.4 2004/11/12 18:19:16 colinmacleod
58  * Change action and form classes to extend MaskAction, MaskForm respectively.
59  *
60  * Revision 1.3 2004/11/12 15:57:19 colinmacleod
61  * Removed dependencies on SSLEXT.
62  * Moved Persistence classes to ivata masks.
63  *
64  * Revision 1.2 2004/11/03 15:31:51 colinmacleod
65  * Change method interfaces to remove log.
66  *
67  * Revision 1.1 2004/09/30 15:15:59 colinmacleod
68  * Split off addressbook elements into security subproject.
69  *
70  * Revision 1.7 2004/07/19 21:58:35 colinmacleod
71  * Changed Vector to List where possible.
72  *
73  * Revision 1.6 2004/07/18 16:16:55 colinmacleod
74  * Added checking that the form is present, and of the right class.
75  *
76  * Revision 1.5 2004/07/13 19:41:12 colinmacleod
77  * Moved project to POJOs from EJBs.
78  * Applied PicoContainer to services layer (replacing session EJBs).
79  * Applied Hibernate to persistence layer (replacing entity EJBs).
80  *
81  * Revision 1.4 2004/03/21 21:16:05 colinmacleod
82  * Shortened name to ivata op.
83  *
84  * Revision 1.3 2004/03/21 20:20:54 colinmacleod
85  * Changed session variable called mailSession to securityServerSession.
86  *
87  * Revision 1.2 2004/02/01 22:00:32 colinmacleod
88  * Added full names to author tags
89  *
90  * Revision 1.1.1.1 2004/01/27 20:57:45 colinmacleod
91  * Moved ivata openportal to SourceForge..
92  *
93  * Revision 1.5 2003/11/13 16:03:15 jano
94  * commitng everything to CVS
95  * can deploy and application is ruuning, can login into
96  *
97  * Revision 1.4 2003/11/07 14:54:15 jano
98  * commitng after fixing some bugs
99  *
100  * Revision 1.3 2003/10/24 13:18:12 jano
101  * fixing some bugs
102  *
103  * Revision 1.2 2003/10/17 12:36:12 jano
104  * fixing problems with building
105  * converting intranet -> portal
106  * Eclipse building
107  *
108  * Revision 1.1.1.1 2003/10/13 20:50:07 colin
109  * Restructured portal into subprojects
110  *
111  * Revision 1.7 2003/07/05 15:57:25 colin
112  * Added possibility for empty jndiPrefix = root default context
113  *
114  * Revision 1.6 2003/03/14 10:26:06 jano
115  * adding backdoor man functionality
116  * backdoor man = briezky
117  *
118  * Revision 1.5 2003/03/12 14:31:53 peter
119  * fixed jndiPrefix handling - one webapp problem
120  *
121  * Revision 1.4 2003/03/11 18:25:45 colin
122  * changes to allow just one webapp
123  *
124  * Revision 1.3 2003/03/05 15:16:48 colin
125  * fixed jndiPrefix to request.getContextPath
126  *
127  * Revision 1.2 2003/02/27 12:03:16 colin
128  * changed forward to redirect to avoid displaying the parameters in the browser
129  *
130  * Revision 1.1 2003/02/24 18:53:57 colin
131  * added to admin
132  *
133  * Revision 1.5 2003/02/06 12:41:22 colin
134  * changed checks for null to checks for isNullOrEmpty (login, forward)
135  *
136  * Revision 1.4 2003/02/06 12:22:25 colin
137  * changed from errors() to isErrors() (a la struts 1.1c)
138  *
139  * Revision 1.3 2003/02/04 17:38:14 colin
140  * updated for new execute interface
141  *
142  * Revision 1.2 2003/01/27 08:59:12 colin
143  * simplified version of login with keepAlive.jsp
144  *
145  * Revision 1.1 2003/01/18 20:29:42 colin
146  * converted login process to struts
147  * added checking for javascript at login
148  * -----------------------------------------------------------------------------
149  */

150 package com.ivata.groupware.admin.security.struts;
151
152 import java.lang.reflect.InvocationTargetException JavaDoc;
153 import java.util.Properties JavaDoc;
154
155 import javax.servlet.http.HttpServletRequest JavaDoc;
156 import javax.servlet.http.HttpServletResponse JavaDoc;
157 import javax.servlet.http.HttpSession JavaDoc;
158
159 import org.apache.commons.beanutils.PropertyUtils;
160 import org.apache.log4j.Logger;
161 import org.apache.struts.action.ActionErrors;
162 import org.apache.struts.action.ActionForm;
163 import org.apache.struts.action.ActionForward;
164 import org.apache.struts.action.ActionMapping;
165 import org.apache.struts.action.ActionMessage;
166 import org.apache.struts.action.ActionMessages;
167 import org.apache.struts.util.RequestUtils;
168 import org.picocontainer.PicoContainer;
169
170 import com.ivata.groupware.admin.security.Security;
171 import com.ivata.groupware.admin.security.server.SecuritySession;
172 import com.ivata.groupware.admin.security.user.UserDO;
173 import com.ivata.groupware.admin.setting.SettingNullException;
174 import com.ivata.groupware.admin.setting.Settings;
175 import com.ivata.groupware.admin.setting.SettingsDataTypeException;
176 import com.ivata.groupware.container.PicoContainerFactory;
177 import com.ivata.groupware.container.persistence.hibernate.HibernateSetupConstants;
178 import com.ivata.mask.MaskFactory;
179 import com.ivata.mask.persistence.FinderException;
180 import com.ivata.mask.util.StringHandling;
181 import com.ivata.mask.util.SystemException;
182 import com.ivata.mask.web.browser.Browser;
183 import com.ivata.mask.web.browser.BrowserConstants;
184 import com.ivata.mask.web.struts.MaskAction;
185 import com.ivata.mask.web.struts.MaskAuthenticator;
186 import com.ivata.mask.web.tag.theme.ThemeConstants;
187
188 /**
189  * <p>This <code>Action</code> is invoked whenever someone tries to
190  * login to the intranet system.</p>
191  *
192  * @since 2003-01-15
193  * @author Colin MacLeod
194  * <a HREF='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
195  * @version $Revision: 1.5 $
196  */

197 public class LoginAction extends MaskAction {
198     private Security security;
199     private Settings settings;
200     /**
201      * <p>
202      * Log4j logger for, well, logging.
203      * </p>
204      */

205     private Logger log = Logger.getLogger(LoginAction.class);
206
207     /**
208      * TODO
209      * @param security
210      * @param settings
211      * @param maskFactory This factory is needed to access the masks and groups
212      * of masks.
213      * @param authenticator used to confirm whether or not the
214      * user should be allowed to continue, in the <code>execute</code> method.
215      */

216     public LoginAction(Security security, Settings settings,
217             MaskFactory maskFactory, MaskAuthenticator authenticator) {
218         super(maskFactory, authenticator);
219         this.security = security;
220         this.settings = settings;
221     }
222
223
224     /**
225      * <p>Overrides and extends (calls) the super class implementation to
226      * tell it not to check the session.</p>
227      *
228      * @param mapping The ActionMapping used to select this instance.
229      * @param form The optional ActionForm bean for this request (if any).
230      * @param request The non-HTTP request we are processing.
231      * @param response The non-HTTP response we are creating.
232      * @exception Exception if the application business logic throws
233      * an exception.
234      * @return this method returns a <code>"success"</code>
235      * <code>ActionForward</code> if the compose session is cancelled or
236      * successfully sent, otherwise a <code>"failure"</code>
237      * <code>ActionForward</code>.
238      *
239      */

240     public ActionForward execute(final ActionMapping mapping,
241             final ActionForm form,
242             final HttpServletRequest JavaDoc request,
243             final HttpServletResponse JavaDoc response) throws Exception JavaDoc {
244         // this prevents us always going around in circles!!
245
setLogin(true);
246         return super.execute(mapping, form, request, response);
247     }
248
249     /**
250      * <p>Overridden from the default intranet implementation to
251      * manipulate user login.</p>
252      *
253      * @param mapping current action mapping from <em>Struts</em> config.
254      * @param log valid logging object to write messages to.
255      * @param errors valid errors object to append errors to. If there are
256      * any errors, the action will return to the input.
257      * @param formParam optional ActionForm bean for this request (if any)
258      * @param request non-HTTP request we are processing
259      * @param response The non-HTTP response we are creating
260      * @param session returned from the <code>request</code> parameter.
261      * @param guestUserName current user name from session. Not needed for
262      * this aciton.
263      * @param settings valid, non-null settings from session.
264      * @exception SystemException if there is any problem which
265      * prevents processing. It will result in the webapp being forwarded
266      * to
267      * the standard error page.
268      * @return this method returns the string used to identify the correct
269      * <em>Struts</em> <code>ActionForward</code> which should follow this
270      * page, or <code>null</code> if it should return to the input.
271      */

272     public String JavaDoc execute(final ActionMapping mapping,
273             final ActionErrors errors,
274             final ActionForm formParam,
275             final HttpServletRequest JavaDoc request,
276             final HttpServletResponse JavaDoc response,
277             final HttpSession JavaDoc session) throws SystemException {
278         ActionForm form = formParam;
279         String JavaDoc forward = null;
280         String JavaDoc help = null;
281         String JavaDoc javaScriptVersion = null;
282         String JavaDoc jndiPrefix = null;
283         String JavaDoc login = null;
284         String JavaDoc password = null;
285
286         String JavaDoc userName = null;
287         SecuritySession securitySession = (SecuritySession) session.getAttribute("securitySession");
288
289         // the value for the forward changes if there is no javascript
290
String JavaDoc errorForward = "login";
291         if ((form == null)
292                 || (securitySession == null)) {
293             return "loginGuestAction";
294         }
295
296         // if the URL is still set to the default database (in memory), check
297
// the user has confirmed this should be so and forward to the setup
298
// page, if not
299
PicoContainerFactory factory = PicoContainerFactory.getInstance();
300         assert (factory != null);
301         PicoContainer container = factory.getGlobalContainer();
302         assert (container != null);
303         Properties JavaDoc hibernateProperties = (Properties JavaDoc) container
304             .getComponentInstance("hibernateProperties");
305         assert (hibernateProperties != null);
306         Boolean JavaDoc setupConfirmed = (Boolean JavaDoc) servlet.getServletContext()
307             .getAttribute(HibernateSetupConstants.CONFIRM_ATTRIBUTE);
308         String JavaDoc uRL = hibernateProperties.getProperty(
309                 HibernateSetupConstants
310                 .HIBERNATE_PROPERTY_DATABASE_URL);
311         assert (uRL != null);
312         if (HibernateSetupConstants.AUTOMATIC_DATABASE_MEMORY_URL
313                     .equals(uRL)
314                 && !Boolean.TRUE.equals(setupConfirmed)) {
315             return "setupAction";
316         }
317
318         try {
319             forward = (String JavaDoc) PropertyUtils.getSimpleProperty(form, "forward");
320             help = (String JavaDoc) PropertyUtils.getSimpleProperty(form, "help");
321             javaScriptVersion = (String JavaDoc) PropertyUtils.getSimpleProperty(form, "javaScriptVersion");
322             jndiPrefix = (String JavaDoc) PropertyUtils.getSimpleProperty(form, "jndiPrefix");
323             login = (String JavaDoc) PropertyUtils.getSimpleProperty(form, "login");
324             password = (String JavaDoc) PropertyUtils.getSimpleProperty(form, "password");
325             userName = ((String JavaDoc) PropertyUtils.getSimpleProperty(form, "userName")).toLowerCase();
326         } catch (InvocationTargetException JavaDoc e) {
327             throw new SystemException(e);
328         } catch (IllegalAccessException JavaDoc e) {
329             throw new SystemException(e);
330         } catch (NoSuchMethodException JavaDoc e) {
331             // if any of the methods are missing, it must be the wrong form...
332
form = RequestUtils.createActionForm(request, mapping, mapping.getModuleConfig(), servlet);
333         }
334         // we can't do anything if we don't even have guest access yet
335
if (securitySession == null) {
336             return "loginGuestAction";
337         }
338
339         String JavaDoc defaultForward = "";
340         // try to find from setting defaultForwaard
341
UserDO user = null;
342         if (!StringHandling.isNullOrEmpty(userName)) {
343             try {
344                 if (log.isDebugEnabled()) {
345                     log.debug("Looking for entity for user name '" + userName + "'");
346                 }
347                 user = security.findUserByName(securitySession, userName);
348                 defaultForward = settings.getStringSetting(securitySession,
349                     "siteDefaultForward",
350                     user);
351             } catch (SettingsDataTypeException e) {
352                 throw new SystemException(e);
353             } catch (SettingNullException e) {
354                 throw new SystemException(e);
355             } catch (FinderException e) {
356                 log.warn("No user found called '" + userName + "'", e);
357                 errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("login.error.login"));
358                 // set login null to login as guest
359
login = null;
360             }
361         }
362         // choose the theme
363
String JavaDoc siteTheme = request.getParameter("theme");
364         // go back to the last used?
365
boolean changeTheme = true;
366         if ("last".equals(siteTheme)) {
367             changeTheme = false;
368             siteTheme = settings.getStringSetting(securitySession,
369                     "siteTheme", user);
370         }
371         session.setAttribute(ThemeConstants.ATTRIBUTE_THEME_NAME, siteTheme);
372         // if the user just changed the theme, use the one specified and go back
373
// again
374
if(StringHandling.isNullOrEmpty(login)) {
375             return "login";
376         }
377
378         // forward was not sent from the form
379
if (StringHandling.isNullOrEmpty(forward)) {
380             forward = defaultForward;
381         }
382
383         try {
384             PropertyUtils.setSimpleProperty(form, "forward", forward);
385         } catch (NoSuchMethodException JavaDoc e) {
386             // send the user back to the login page - this form is no use!
387
form = RequestUtils.createActionForm(request, mapping, mapping.getModuleConfig(), servlet);
388             try {
389                 PropertyUtils.setSimpleProperty(form, "forward", forward);
390             } catch (IllegalAccessException JavaDoc e1) {
391                 e1.printStackTrace();
392             } catch (InvocationTargetException JavaDoc e1) {
393                 e1.printStackTrace();
394             } catch (NoSuchMethodException JavaDoc e1) {
395                 e1.printStackTrace();
396             }
397             return null;
398         } catch (InvocationTargetException JavaDoc e) {
399             throw new SystemException(e);
400         } catch (IllegalAccessException JavaDoc e) {
401             throw new SystemException(e);
402         }
403         Browser browser = null;
404
405         // initialize the browser object
406
if ((javaScriptVersion != null) &&
407             javaScriptVersion.trim().equals("")) {
408             javaScriptVersion = null;
409         }
410         browser = new Browser(request.getHeader("User-Agent"), javaScriptVersion);
411         session.setAttribute("browser", browser);
412         // this is where we actually try to login
413
try {
414             if (log.isInfoEnabled()) {
415                 log.info("Logging in user '" + userName + "' for real (not guest).");
416             }
417             session.setAttribute("securitySession", securitySession =
418                 security.login(user, password));
419         } catch (Exception JavaDoc e) {
420             // show the password only if the setting allows us to
421
String JavaDoc logPassword = "**********";
422             try {
423                 securitySession = security.loginGuest();
424                 Boolean JavaDoc debugPassword = settings.getBooleanSetting(
425                         securitySession,
426                         "siteLoginDebugPassword", null);
427                 if ((debugPassword != null)
428                         && debugPassword.booleanValue()) {
429                     logPassword = password;
430                 }
431             } catch (Exception JavaDoc e1) {
432                 // nothing we can do - just log the error
433
log.error("Failed to access setting 'siteLoginDebugPassword'.",
434                         e1);
435             }
436             log.warn ("Failed to login user '"
437                     + userName
438                     + "', password '"
439                     + logPassword
440                     + "'", e);
441             errors.add(ActionMessages.GLOBAL_MESSAGE,
442                     new ActionMessage("login.error.login"));
443         }
444         // if there is no javascript on the browser, handle that
445
// TODO: - javascript could be made optional with just a warning by
446
// placing the if(!errors.empty()) { section above this comment
447
if (javaScriptVersion == null) {
448             if (log.isInfoEnabled()) {
449                 log.info("Javascript is unavailable on user's browser.");
450             }
451             // if you don't have javascript, we show a special login designed
452
// to help you activate (and check it is working)
453
errorForward = "loginJavaScript";
454             Integer JavaDoc browserType = browser.getType();
455             String JavaDoc errorKey;
456
457             if (BrowserConstants.TYPE_INTERNET_EXPLORER.equals(browserType)) {
458                 if (browser.getVersion().compareTo("5") >= 0) {
459                     if (log.isDebugEnabled()) {
460                         log.debug("Identified IE5 browser.");
461                     }
462                     // they changed the place for javascript preferences. Grrr.
463
errorKey = "login.error.javascript.iexplore5";
464                 } else {
465                     if (log.isDebugEnabled()) {
466                         log.debug("Identified IE browser.");
467                     }
468                     errorKey = "login.error.javascript.iexplore";
469                 }
470             } else if (BrowserConstants.TYPE_MOZILLA.equals(browserType) ||
471                 BrowserConstants.TYPE_NETSCAPE.equals(browserType)) {
472                 if (log.isDebugEnabled()) {
473                     log.debug("Identified Netscape/Mozilla browser.");
474                 }
475                 errorKey = "login.error.javascript.netscape";
476             } else if (BrowserConstants.TYPE_OPERA.equals(browserType)) {
477                 if (browser.getVersion().compareTo("6") >= 0) {
478                     // they changed the place for javascript preferences. Grrr.
479
errorKey = "login.error.javascript.opera6";
480                     if (log.isDebugEnabled()) {
481                         log.debug("Identified Opera 6 browser.");
482                     }
483                 } else {
484                     errorKey = "login.error.javascript.opera";
485                     if (log.isDebugEnabled()) {
486                         log.debug("Identified Opera browser.");
487                     }
488                 }
489             } else {
490                 errorKey = "login.error.javascript.unknown";
491                 if (log.isDebugEnabled()) {
492                     log.debug("Could not identify browser.");
493                 }
494             }
495             errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(errorKey));
496         }
497         // if there are errors, you can't get in!
498
if (!errors.isEmpty()) {
499             if (log.isInfoEnabled()) {
500                 log.info("Errors found for user '" + userName + "'.");
501             }
502             return errorForward;
503         }
504         if (log.isInfoEnabled()) {
505             log.info("Login successful for user '" + userName + "'.");
506         }
507         // if we got here, that means we now have a logged in user
508
session.setAttribute("userName", userName);
509         request.setAttribute("loginForward", forward);
510
511         // if the user changed the theme, save it in the settings for the next
512
// time
513
if (changeTheme) {
514             settings.amendSetting(securitySession, "siteTheme", siteTheme,
515                     user);
516         }
517         return forward;
518     }
519 }
520
Popular Tags