View Javadoc

1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  
19  package org.itracker.web.actions.user;
20  
21  import java.io.IOException;
22  import java.lang.reflect.InvocationTargetException;
23  
24  import javax.servlet.ServletException;
25  import javax.servlet.http.HttpServletRequest;
26  import javax.servlet.http.HttpServletResponse;
27  
28  import org.apache.commons.beanutils.PropertyUtils;
29  import org.apache.log4j.Logger;
30  import org.apache.struts.action.ActionForm;
31  import org.apache.struts.action.ActionForward;
32  import org.apache.struts.action.ActionMapping;
33  import org.apache.struts.action.ActionMessage;
34  import org.apache.struts.action.ActionMessages;
35  import org.itracker.model.User;
36  import org.itracker.services.UserService;
37  import org.itracker.services.exceptions.AuthenticatorException;
38  import org.itracker.services.exceptions.PasswordException;
39  import org.itracker.services.util.AuthenticationConstants;
40  import org.itracker.services.util.UserUtilities;
41  import org.itracker.web.actions.base.ItrackerBaseAction;
42  import org.itracker.web.filters.ExecuteAlwaysFilter;
43  import org.itracker.web.forms.LoginForm;
44  import org.itracker.web.util.Constants;
45  import org.itracker.web.util.LoginUtilities;
46  import org.itracker.web.util.SessionManager;
47  
48  public class LoginAction extends ItrackerBaseAction {
49  	private static final Logger log = Logger.getLogger(LoginAction.class);
50  
51  
52  
53  	public ActionForward execute(ActionMapping mapping, ActionForm form,
54  			HttpServletRequest request, HttpServletResponse response)
55  			throws ServletException, IOException {
56  
57      	ActionMessages errors = new ActionMessages();
58      	
59  		ActionForward errorMapping = null;
60  		String login = null;
61  		
62  		log.debug("execute: called");
63  
64  		String pageTitleKey = "itracker.web.login.title";
65  		String pageTitleArg = "";
66  		request.setAttribute("pageTitleKey", pageTitleKey);
67  		request.setAttribute("pageTitleArg", pageTitleArg);
68  		Boolean skipLogin = false;
69  		if (form instanceof LoginForm) {
70  			skipLogin = ((LoginForm)form).isSkip();
71  		}
72  		/*
73  		 *	SKIP credentials validation when forwarded to login. 
74  		 */
75  		if (skipLogin) {
76  			log.debug("execute: forwarded, skip login.");
77  			saveErrors(request, new ActionMessages());
78  			return mapping.findForward("login");
79  		} else {
80  			try {
81  				UserService userService = getITrackerServices()
82  						.getUserService();
83  
84  				try {
85  					User user = null;
86  					String encPassword = null;
87  
88  					int authType = LoginUtilities.getRequestAuthType(request);
89  
90  					if (authType == AuthenticationConstants.AUTH_TYPE_PASSWORD_PLAIN) {
91  						login = (String) request
92  								.getAttribute(Constants.AUTH_LOGIN_KEY);
93  						String authenticator = (String) request
94  								.getAttribute(Constants.AUTH_VALUE_KEY);
95  						if (login == null || login.equals("")) {
96  							login = (String) PropertyUtils.getSimpleProperty(
97  									form, "login");
98  						}
99  						if (authenticator == null || authenticator.equals("")) {
100 							authenticator = (String) PropertyUtils
101 									.getSimpleProperty(form, "password");
102 						}
103 						encPassword = UserUtilities
104 								.encryptPassword(authenticator);
105 
106 						log
107 								.debug("Attempting login with plaintext password for user "
108 										+ login);
109 						user = userService
110 								.checkLogin(
111 										login,
112 										authenticator,
113 										AuthenticationConstants.AUTH_TYPE_PASSWORD_PLAIN,
114 										AuthenticationConstants.REQ_SOURCE_WEB);
115 					} else if (authType == AuthenticationConstants.AUTH_TYPE_PASSWORD_ENC) {
116 						login = (String) request
117 								.getAttribute(Constants.AUTH_LOGIN_KEY);
118 						String authenticator = (String) request
119 								.getAttribute(Constants.AUTH_VALUE_KEY);
120 						if (login == null || login.equals("")) {
121 							login = (String) PropertyUtils.getSimpleProperty(
122 									form, "login");
123 						}
124 						if (authenticator == null || authenticator.equals("")) {
125 							authenticator = (String) PropertyUtils
126 									.getSimpleProperty(form, "encpassword");
127 						}
128 						encPassword = authenticator;
129 
130 						log
131 								.debug("Attempting login with encrypted password for user "
132 										+ login);
133 						user = userService.checkLogin(login, authenticator,
134 								AuthenticationConstants.AUTH_TYPE_PASSWORD_ENC,
135 								AuthenticationConstants.REQ_SOURCE_WEB);
136 					} else if (authType == AuthenticationConstants.AUTH_TYPE_REQUEST) {
137 						log.debug("Attempting login with request object");
138 						user = userService.checkLogin(login, request,
139 								AuthenticationConstants.AUTH_TYPE_REQUEST,
140 								AuthenticationConstants.REQ_SOURCE_WEB);
141 					} else {
142 						log
143 								.debug("Attempting login with with unknown auth type");
144 						user = userService.checkLogin(login, request,
145 								AuthenticationConstants.AUTH_TYPE_UNKNOWN,
146 								AuthenticationConstants.REQ_SOURCE_WEB);
147 					}
148 
149 					if (user == null) {
150 						throw new AuthenticatorException(
151 								AuthenticatorException.UNKNOWN_USER);
152 					}
153 					login = user.getLogin();
154 
155 					LoginUtilities.setupSession(user, encPassword, request, response);
156 					SessionManager.createSession(login);
157 
158 					try {
159 						return ExecuteAlwaysFilter.forwardToOnLoginSuccess(
160 								request, response);
161 					} catch (Exception e) {
162 						log.error("execute: failed to redirect.", e);
163 					}
164 
165 					// TODO: Deprecated code. Can we get rid of it? Why is it so
166 					// complicated??
167 					// We only want to iknow if success or no success
168 
169 					String redirect = request
170 							.getParameter(Constants.AUTH_REDIRECT_KEY);
171 
172 					log.debug("Redirect URL from request param = " + redirect);
173 					if (redirect == null || "".equals(redirect)) {
174 						redirect = (String) request
175 								.getAttribute(Constants.AUTH_REDIRECT_KEY);
176 						log.debug("Redirect URL from request attribute = "
177 								+ redirect);
178 					}
179 					int redirectIndex = (redirect == null ? -1 : redirect
180 							.indexOf("?" + Constants.AUTH_REDIRECT_KEY + "="));
181 					if (redirectIndex > -1) {
182 						int extraParamIndex = redirect.indexOf("&",
183 								redirectIndex);
184 						int lastParamIndex = redirect.lastIndexOf("&",
185 								redirectIndex);
186 						if (log.isDebugEnabled()) {
187 							log.debug("Original redirect URL = " + redirect);
188 							log.debug("Redirect Index: " + redirectIndex
189 									+ "  ExtraParamIndex: " + extraParamIndex
190 									+ "  LastParamIndex: " + lastParamIndex);
191 						}
192 						if (extraParamIndex > -1 && lastParamIndex > -1) {
193 							redirect = redirect.substring(0, redirectIndex)
194 									+ "?"
195 									+ redirect.substring(extraParamIndex + 1,
196 											lastParamIndex);
197 						} else if (extraParamIndex > -1) {
198 							redirect = redirect.substring(0, redirectIndex)
199 									+ "?"
200 									+ redirect.substring(extraParamIndex + 1);
201 						} else {
202 							redirect = redirect.substring(0, redirectIndex);
203 						}
204 					}
205 					if (log.isInfoEnabled()) {
206 						log.info("User "
207 								+ (user != null ? user.getLogin() : "UNKNOWN")
208 								+ " logged in successfully.");
209 					}
210 					if (redirect.trim().length() == 0) {
211 						log
212 								.info("Action is trying to forward to Forward index");
213 						return mapping.findForward("index");
214 					} else {
215 						if (log.isDebugEnabled()) {
216 							log.debug("Redirecting to " + redirect);
217 						}
218 						return new ActionForward(redirect, true);
219 					}
220 				} catch (IllegalStateException ise) {
221 					if (log.isDebugEnabled()) {
222 						log.debug("IllegalStateException caught during login.",
223 								ise);
224 					}
225 					errors
226 							.add(ActionMessages.GLOBAL_MESSAGE,
227 									new ActionMessage(
228 											"itracker.web.error.login.system"));
229 				} catch (AuthenticatorException le) {
230 					if (log.isDebugEnabled()) {
231 						log.debug("Login Exception for user "
232 								+ (login != null ? login : "UNKNOWN")
233 								+ ". Type = " + le.getType(), le);
234 					}
235 					// skip errors if forwarded by execute-always servlet-filter
236 					if (request.getSession().getAttribute("loginForwarded") != null) {
237 						request.getSession().removeAttribute("loginForwarded");
238 						errors.clear();
239 					}
240 					// TODO: no information about login-credentials should be
241 					// shown
242 					else if (le.getType() == AuthenticatorException.INVALID_PASSWORD) {
243 						errors.add(ActionMessages.GLOBAL_MESSAGE,
244 								new ActionMessage(
245 										"itracker.web.error.login.unknown")
246 						// "itracker.web.error.login.badpass")
247 								);
248 					} else if (le.getType() == AuthenticatorException.INACTIVE_ACCOUNT) {
249 						errors.add(ActionMessages.GLOBAL_MESSAGE,
250 								new ActionMessage(
251 										"itracker.web.error.login.inactive"));
252 					} else if (le.getType() == AuthenticatorException.UNKNOWN_USER) {
253 						errors.add(ActionMessages.GLOBAL_MESSAGE,
254 								new ActionMessage(
255 										"itracker.web.error.login.unknown"));
256 					} else if (le.getType() == AuthenticatorException.INVALID_AUTHENTICATION_TYPE) {
257 						errors.add(ActionMessages.GLOBAL_MESSAGE,
258 								new ActionMessage(
259 										"itracker.web.error.login.system"));
260 					} else if (le.getType() == AuthenticatorException.CUSTOM_ERROR) {
261 						errors.add(ActionMessages.GLOBAL_MESSAGE,
262 								new ActionMessage(le.getMessageKey()));
263 					} else {
264 						errors.add(ActionMessages.GLOBAL_MESSAGE,
265 								new ActionMessage(
266 										"itracker.web.error.login.system"));
267 					}
268 
269 					if (le.getErrorPageType() == AuthenticatorException.ERRORPAGE_TYPE_FORWARD) {
270 						errorMapping = mapping.findForward(le
271 								.getErrorPageValue());
272 					} else if (le.getErrorPageType() == AuthenticatorException.ERRORPAGE_TYPE_URL) {
273 						errorMapping = new ActionForward(le.getErrorPageValue());
274 					}
275 				} catch (IllegalAccessException e) {
276 					errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
277 					"itracker.web.error.login.system"));
278 				} catch (InvocationTargetException e) {
279 					errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
280 					"itracker.web.error.login.system"));
281 				} catch (NoSuchMethodException e) {
282 					errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
283 					"itracker.web.error.login.system"));
284 				} catch (PasswordException e) {
285 					errors.add(ActionMessages.GLOBAL_MESSAGE,
286 							new ActionMessage(
287 									"itracker.web.error.login.unknown"));
288 				}
289 				log.info("User " + (login != null ? login : "UNKNOWN")
290 						+ " login unsucessful.");
291 			} catch (RuntimeException e) {
292 				errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
293 						"itracker.web.error.login.system"));
294 				log.error("System Error.", e);
295 			} finally {
296 				if (!errors.isEmpty()) {
297 					LogoffAction logoff = new LogoffAction();
298 					logoff.clearSession(login, request, response);
299 					saveErrors(request, errors);
300 				}
301 			}
302 		}
303 		return (errorMapping == null ? mapping.findForward("login")
304 				: errorMapping);
305 	}
306 
307 
308 }