1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.action;
16  
17  import com.liferay.portal.CookieNotSupportedException;
18  import com.liferay.portal.NoSuchUserException;
19  import com.liferay.portal.PasswordExpiredException;
20  import com.liferay.portal.SendPasswordException;
21  import com.liferay.portal.SystemException;
22  import com.liferay.portal.UserEmailAddressException;
23  import com.liferay.portal.UserIdException;
24  import com.liferay.portal.UserLockoutException;
25  import com.liferay.portal.UserPasswordException;
26  import com.liferay.portal.UserScreenNameException;
27  import com.liferay.portal.kernel.captcha.CaptchaTextException;
28  import com.liferay.portal.kernel.captcha.CaptchaUtil;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.servlet.HttpHeaders;
32  import com.liferay.portal.kernel.servlet.SessionErrors;
33  import com.liferay.portal.kernel.servlet.SessionMessages;
34  import com.liferay.portal.kernel.util.Constants;
35  import com.liferay.portal.kernel.util.GetterUtil;
36  import com.liferay.portal.kernel.util.HttpUtil;
37  import com.liferay.portal.kernel.util.ParamUtil;
38  import com.liferay.portal.kernel.util.PropsKeys;
39  import com.liferay.portal.kernel.util.StringPool;
40  import com.liferay.portal.kernel.util.Validator;
41  import com.liferay.portal.model.Company;
42  import com.liferay.portal.model.CompanyConstants;
43  import com.liferay.portal.model.User;
44  import com.liferay.portal.security.auth.AuthException;
45  import com.liferay.portal.security.auth.Authenticator;
46  import com.liferay.portal.service.UserLocalServiceUtil;
47  import com.liferay.portal.theme.ThemeDisplay;
48  import com.liferay.portal.util.CookieKeys;
49  import com.liferay.portal.util.PortalUtil;
50  import com.liferay.portal.util.PortletKeys;
51  import com.liferay.portal.util.PrefsPropsUtil;
52  import com.liferay.portal.util.PropsValues;
53  import com.liferay.portal.util.WebKeys;
54  import com.liferay.portlet.PortletURLImpl;
55  import com.liferay.util.Encryptor;
56  import com.liferay.util.servlet.SessionParameters;
57  
58  import java.util.ArrayList;
59  import java.util.Enumeration;
60  import java.util.HashMap;
61  import java.util.List;
62  import java.util.Map;
63  
64  import javax.portlet.PortletMode;
65  import javax.portlet.PortletRequest;
66  import javax.portlet.PortletURL;
67  import javax.portlet.WindowState;
68  
69  import javax.servlet.http.Cookie;
70  import javax.servlet.http.HttpServletRequest;
71  import javax.servlet.http.HttpServletResponse;
72  import javax.servlet.http.HttpSession;
73  
74  import org.apache.struts.action.Action;
75  import org.apache.struts.action.ActionForm;
76  import org.apache.struts.action.ActionForward;
77  import org.apache.struts.action.ActionMapping;
78  
79  /**
80   * <a href="LoginAction.java.html"><b><i>View Source</i></b></a>
81   *
82   * @author Brian Wing Shun Chan
83   * @author Scott Lee
84   */
85  public class LoginAction extends Action {
86  
87      public static String getLogin(
88              HttpServletRequest request, String paramName, Company company)
89          throws SystemException {
90  
91          String login = request.getParameter(paramName);
92  
93          if ((login == null) || (login.equals(StringPool.NULL))) {
94              login = GetterUtil.getString(
95                  CookieKeys.getCookie(request, CookieKeys.LOGIN));
96  
97              if (PropsValues.COMPANY_LOGIN_PREPOPULATE_DOMAIN &&
98                  Validator.isNull(login) &&
99                  company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
100 
101                 login = "@" + company.getMx();
102             }
103         }
104 
105         return login;
106     }
107 
108     public static void login(
109             HttpServletRequest request, HttpServletResponse response,
110             String login, String password, boolean rememberMe)
111         throws Exception {
112 
113         CookieKeys.validateSupportCookie(request);
114 
115         HttpSession session = request.getSession();
116 
117         long userId = GetterUtil.getLong(login);
118 
119         int authResult = Authenticator.FAILURE;
120 
121         Company company = PortalUtil.getCompany(request);
122 
123         Map<String, String[]> headerMap = new HashMap<String, String[]>();
124 
125         Enumeration<String> enu1 = request.getHeaderNames();
126 
127         while (enu1.hasMoreElements()) {
128             String name = enu1.nextElement();
129 
130             Enumeration<String> enu2 = request.getHeaders(name);
131 
132             List<String> headers = new ArrayList<String>();
133 
134             while (enu2.hasMoreElements()) {
135                 String value = enu2.nextElement();
136 
137                 headers.add(value);
138             }
139 
140             headerMap.put(name, headers.toArray(new String[headers.size()]));
141         }
142 
143         Map<String, String[]> parameterMap = request.getParameterMap();
144 
145         if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
146             authResult = UserLocalServiceUtil.authenticateByEmailAddress(
147                 company.getCompanyId(), login, password, headerMap,
148                 parameterMap);
149 
150             userId = UserLocalServiceUtil.getUserIdByEmailAddress(
151                 company.getCompanyId(), login);
152         }
153         else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_SN)) {
154             authResult = UserLocalServiceUtil.authenticateByScreenName(
155                 company.getCompanyId(), login, password, headerMap,
156                 parameterMap);
157 
158             userId = UserLocalServiceUtil.getUserIdByScreenName(
159                 company.getCompanyId(), login);
160         }
161         else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_ID)) {
162             authResult = UserLocalServiceUtil.authenticateByUserId(
163                 company.getCompanyId(), userId, password, headerMap,
164                 parameterMap);
165         }
166 
167         if (authResult == Authenticator.SUCCESS) {
168             if (PropsValues.SESSION_ENABLE_PHISHING_PROTECTION) {
169 
170                 // Invalidate the previous session to prevent phishing
171 
172                 String[] protectedAttributeNames =
173                     PropsValues.SESSION_PHISHING_PROTECTED_ATTRIBUTES;
174 
175                 Map<String, Object> protectedAttributes =
176                     new HashMap<String, Object>();
177 
178                 for (String protectedAttributeName : protectedAttributeNames) {
179                     Object protectedAttributeValue = session.getAttribute(
180                         protectedAttributeName);
181 
182                     if (protectedAttributeValue == null) {
183                         continue;
184                     }
185 
186                     protectedAttributes.put(
187                         protectedAttributeName, protectedAttributeValue);
188                 }
189 
190                 try {
191                     session.invalidate();
192                 }
193                 catch (IllegalStateException ise) {
194 
195                     // This only happens in Geronimo
196 
197                     if (_log.isWarnEnabled()) {
198                         _log.warn(ise.getMessage());
199                     }
200                 }
201 
202                 session = request.getSession(true);
203 
204                 for (String protectedAttributeName : protectedAttributeNames) {
205                     Object protectedAttributeValue = protectedAttributes.get(
206                         protectedAttributeName);
207 
208                     if (protectedAttributeValue == null) {
209                         continue;
210                     }
211 
212                     session.setAttribute(
213                         protectedAttributeName, protectedAttributeValue);
214                 }
215             }
216 
217             // Set cookies
218 
219             String domain = CookieKeys.getDomain(request);
220 
221             User user = UserLocalServiceUtil.getUserById(userId);
222 
223             String userIdString = String.valueOf(userId);
224 
225             session.setAttribute("j_username", userIdString);
226             session.setAttribute("j_password", user.getPassword());
227             session.setAttribute("j_remoteuser", userIdString);
228 
229             session.setAttribute(WebKeys.USER_PASSWORD, password);
230 
231             Cookie companyIdCookie = new Cookie(
232                 CookieKeys.COMPANY_ID, String.valueOf(company.getCompanyId()));
233 
234             if (Validator.isNotNull(domain)) {
235                 companyIdCookie.setDomain(domain);
236             }
237 
238             companyIdCookie.setPath(StringPool.SLASH);
239 
240             Cookie idCookie = new Cookie(
241                 CookieKeys.ID,
242                 UserLocalServiceUtil.encryptUserId(userIdString));
243 
244             if (Validator.isNotNull(domain)) {
245                 idCookie.setDomain(domain);
246             }
247 
248             idCookie.setPath(StringPool.SLASH);
249 
250             Cookie passwordCookie = new Cookie(
251                 CookieKeys.PASSWORD,
252                 Encryptor.encrypt(company.getKeyObj(), password));
253 
254             if (Validator.isNotNull(domain)) {
255                 passwordCookie.setDomain(domain);
256             }
257 
258             passwordCookie.setPath(StringPool.SLASH);
259 
260             Cookie rememberMeCookie = new Cookie(
261                 CookieKeys.REMEMBER_ME, Boolean.TRUE.toString());
262 
263             if (Validator.isNotNull(domain)) {
264                 rememberMeCookie.setDomain(domain);
265             }
266 
267             rememberMeCookie.setPath(StringPool.SLASH);
268 
269             int loginMaxAge = PropsValues.COMPANY_SECURITY_AUTO_LOGIN_MAX_AGE;
270 
271             if (PropsValues.SESSION_DISABLED) {
272                 rememberMe = true;
273             }
274 
275             if (rememberMe) {
276                 companyIdCookie.setMaxAge(loginMaxAge);
277                 idCookie.setMaxAge(loginMaxAge);
278                 passwordCookie.setMaxAge(loginMaxAge);
279                 rememberMeCookie.setMaxAge(loginMaxAge);
280             }
281             else {
282 
283                 // This was explicitly changed from 0 to -1 so that the cookie
284                 // lasts as long as the browser. This allows an external servlet
285                 // wrapped in AutoLoginFilter to work throughout the client
286                 // connection. The cookies ARE removed on an actual logout, so
287                 // there is no security issue. See LEP-4678 and LEP-5177.
288 
289                 companyIdCookie.setMaxAge(-1);
290                 idCookie.setMaxAge(-1);
291                 passwordCookie.setMaxAge(-1);
292                 rememberMeCookie.setMaxAge(0);
293             }
294 
295             Cookie loginCookie = new Cookie(CookieKeys.LOGIN, login);
296 
297             if (Validator.isNotNull(domain)) {
298                 loginCookie.setDomain(domain);
299             }
300 
301             loginCookie.setMaxAge(loginMaxAge);
302             loginCookie.setPath(StringPool.SLASH);
303 
304             Cookie screenNameCookie = new Cookie(
305                 CookieKeys.SCREEN_NAME,
306                 Encryptor.encrypt(company.getKeyObj(), user.getScreenName()));
307 
308             if (Validator.isNotNull(domain)) {
309                 screenNameCookie.setDomain(domain);
310             }
311 
312             screenNameCookie.setMaxAge(loginMaxAge);
313             screenNameCookie.setPath(StringPool.SLASH);
314 
315             boolean secure = request.isSecure();
316 
317             if (secure) {
318                 Boolean httpsInitial = (Boolean)session.getAttribute(
319                     WebKeys.HTTPS_INITIAL);
320 
321                 if ((httpsInitial == null) || !httpsInitial.booleanValue()) {
322                     secure = false;
323                 }
324             }
325 
326             CookieKeys.addCookie(request, response, companyIdCookie, secure);
327             CookieKeys.addCookie(request, response, idCookie, secure);
328             CookieKeys.addCookie(request, response, passwordCookie, secure);
329             CookieKeys.addCookie(request, response, rememberMeCookie, secure);
330             CookieKeys.addCookie(request, response, loginCookie, secure);
331             CookieKeys.addCookie(request, response, screenNameCookie, secure);
332         }
333         else {
334             throw new AuthException();
335         }
336     }
337 
338     public static void sendPassword(HttpServletRequest request)
339         throws Exception {
340 
341         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
342             WebKeys.THEME_DISPLAY);
343 
344         Company company = themeDisplay.getCompany();
345 
346         if (!company.isSendPassword()) {
347             return;
348         }
349 
350         String emailAddress = ParamUtil.getString(request, "emailAddress");
351 
352         String remoteAddr = request.getRemoteAddr();
353         String remoteHost = request.getRemoteHost();
354         String userAgent = request.getHeader(HttpHeaders.USER_AGENT);
355 
356         UserLocalServiceUtil.sendPassword(
357             PortalUtil.getCompanyId(request), emailAddress, remoteAddr,
358             remoteHost, userAgent);
359     }
360 
361     public ActionForward execute(
362             ActionMapping mapping, ActionForm form, HttpServletRequest request,
363             HttpServletResponse response)
364         throws Exception {
365 
366         if (PropsValues.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS &&
367             !request.isSecure()) {
368 
369             ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
370                 WebKeys.THEME_DISPLAY);
371 
372             StringBuilder sb = new StringBuilder();
373 
374             sb.append(PortalUtil.getPortalURL(request, true));
375             sb.append(themeDisplay.getURLSignIn());
376 
377             response.sendRedirect(sb.toString());
378 
379             return null;
380         }
381 
382         HttpSession session = request.getSession();
383 
384         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
385             WebKeys.THEME_DISPLAY);
386 
387         if (session.getAttribute("j_username") != null &&
388             session.getAttribute("j_password") != null) {
389 
390             if (PropsValues.PORTAL_JAAS_ENABLE) {
391                 return mapping.findForward("/portal/touch_protected.jsp");
392             }
393             else {
394                 response.sendRedirect(themeDisplay.getPathMain());
395 
396                 return null;
397             }
398         }
399 
400         String cmd = ParamUtil.getString(request, Constants.CMD);
401 
402         if (cmd.equals("already-registered")) {
403             try {
404                 login(request, response);
405 
406                 if (PropsValues.PORTAL_JAAS_ENABLE) {
407                     return mapping.findForward("/portal/touch_protected.jsp");
408                 }
409                 else {
410                     String redirect = ParamUtil.getString(request, "redirect");
411 
412                     if (Validator.isNotNull(redirect)) {
413                         redirect = PortalUtil.escapeRedirect(redirect);
414 
415                         response.sendRedirect(redirect);
416                     }
417                     else {
418                         response.sendRedirect(themeDisplay.getPathMain());
419                     }
420 
421                     return null;
422                 }
423             }
424             catch (Exception e) {
425                 if (e instanceof AuthException) {
426                     Throwable cause = e.getCause();
427 
428                     if (cause instanceof PasswordExpiredException ||
429                         cause instanceof UserLockoutException) {
430 
431                         SessionErrors.add(request, cause.getClass().getName());
432                     }
433                     else {
434                         SessionErrors.add(request, e.getClass().getName());
435                     }
436 
437                     return mapping.findForward("portal.login");
438                 }
439                 else if (e instanceof CookieNotSupportedException ||
440                          e instanceof NoSuchUserException ||
441                          e instanceof PasswordExpiredException ||
442                          e instanceof UserEmailAddressException ||
443                          e instanceof UserIdException ||
444                          e instanceof UserLockoutException ||
445                          e instanceof UserPasswordException ||
446                          e instanceof UserScreenNameException) {
447 
448                     SessionErrors.add(request, e.getClass().getName());
449 
450                     return mapping.findForward("portal.login");
451                 }
452                 else {
453                     PortalUtil.sendError(e, request, response);
454 
455                     return null;
456                 }
457             }
458         }
459         else if (cmd.equals("forgot-password")) {
460             try {
461                 if (PropsValues.CAPTCHA_CHECK_PORTAL_SEND_PASSWORD) {
462                     CaptchaUtil.check(request);
463                 }
464 
465                 sendPassword(request);
466 
467                 SessionMessages.add(request, "request_processed");
468 
469                 return mapping.findForward("portal.login");
470             }
471             catch (Exception e) {
472                 if (e instanceof CaptchaTextException ||
473                     e instanceof NoSuchUserException ||
474                     e instanceof SendPasswordException ||
475                     e instanceof UserEmailAddressException) {
476 
477                     SessionErrors.add(request, e.getClass().getName());
478 
479                     return mapping.findForward("portal.login");
480                 }
481                 else {
482                     PortalUtil.sendError(e, request, response);
483 
484                     return null;
485                 }
486             }
487         }
488         else {
489             String redirect = PortalUtil.getCommunityLoginURL(themeDisplay);
490 
491             if (Validator.isNull(redirect)) {
492                 redirect = PropsValues.AUTH_LOGIN_URL;
493             }
494 
495             if (Validator.isNull(redirect)) {
496                 PortletURL portletURL = new PortletURLImpl(
497                     request, PortletKeys.LOGIN, themeDisplay.getPlid(),
498                     PortletRequest.RENDER_PHASE);
499 
500                 portletURL.setWindowState(WindowState.MAXIMIZED);
501                 portletURL.setPortletMode(PortletMode.VIEW);
502 
503                 portletURL.setParameter("saveLastPath", "0");
504                 portletURL.setParameter("struts_action", "/login/view");
505 
506                 redirect = portletURL.toString();
507             }
508 
509             String loginRedirect = ParamUtil.getString(request, "redirect");
510 
511             if (Validator.isNotNull(loginRedirect)) {
512                 if (PrefsPropsUtil.getBoolean(
513                         themeDisplay.getCompanyId(), PropsKeys.CAS_AUTH_ENABLED,
514                         PropsValues.CAS_AUTH_ENABLED)) {
515 
516                     redirect = loginRedirect;
517                 }
518                 else {
519                     String loginPortletNamespace =
520                         PortalUtil.getPortletNamespace(
521                             PropsValues.AUTH_LOGIN_PORTLET_NAME);
522 
523                     String loginRedirectParameter = loginPortletNamespace +
524                         "redirect";
525 
526                     redirect = HttpUtil.setParameter(
527                         redirect, "p_p_id",
528                         PropsValues.AUTH_LOGIN_PORTLET_NAME);
529                     redirect = HttpUtil.setParameter(
530                         redirect, "p_p_lifecycle", "0");
531                     redirect = HttpUtil.setParameter(
532                         redirect, loginRedirectParameter, loginRedirect);
533                 }
534             }
535 
536             if (Validator.isNotNull(redirect)) {
537                 response.sendRedirect(redirect);
538 
539                 return null;
540             }
541             else {
542                 return mapping.findForward("portal.login");
543             }
544         }
545     }
546 
547     protected void login(
548             HttpServletRequest request, HttpServletResponse response)
549         throws Exception {
550 
551         String login = ParamUtil.getString(request, "login").toLowerCase();
552         String password = ParamUtil.getString(
553             request, SessionParameters.get(request, "password"));
554         boolean rememberMe = ParamUtil.getBoolean(request, "rememberMe");
555 
556         login(request, response, login, password, rememberMe);
557     }
558 
559     private static Log _log = LogFactoryUtil.getLog(LoginAction.class);
560 
561 }