001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.servlet.filters.autologin;
016    
017    import com.liferay.portal.NoSuchUserException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.InstancePool;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.model.User;
026    import com.liferay.portal.model.UserTracker;
027    import com.liferay.portal.security.auth.AutoLogin;
028    import com.liferay.portal.security.pwd.PwdEncryptor;
029    import com.liferay.portal.service.UserLocalServiceUtil;
030    import com.liferay.portal.service.UserTrackerLocalServiceUtil;
031    import com.liferay.portal.servlet.filters.BasePortalFilter;
032    import com.liferay.portal.util.PortalInstances;
033    import com.liferay.portal.util.PortalUtil;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portal.util.WebKeys;
036    
037    import java.util.List;
038    import java.util.concurrent.CopyOnWriteArrayList;
039    
040    import javax.servlet.FilterChain;
041    import javax.servlet.http.HttpServletRequest;
042    import javax.servlet.http.HttpServletResponse;
043    import javax.servlet.http.HttpSession;
044    
045    /**
046     * @author Brian Wing Shun Chan
047     * @author Raymond Augé
048     */
049    public class AutoLoginFilter extends BasePortalFilter {
050    
051            public static void registerAutoLogin(AutoLogin autoLogin) {
052                    _autoLogins.add(autoLogin);
053            }
054    
055            public static void unregisterAutoLogin(AutoLogin autoLogin) {
056                    _autoLogins.remove(autoLogin);
057            }
058    
059            public AutoLoginFilter() {
060                    for (String autoLoginClassName : PropsValues.AUTO_LOGIN_HOOKS) {
061                            AutoLogin autoLogin = (AutoLogin)InstancePool.get(
062                                    autoLoginClassName);
063    
064                            _autoLogins.add(autoLogin);
065                    }
066            }
067    
068            protected String getLoginRemoteUser(
069                            HttpServletRequest request, HttpServletResponse response,
070                            HttpSession session, String[] credentials)
071                    throws Exception {
072    
073                    if ((credentials == null) || (credentials.length != 3)) {
074                            return null;
075                    }
076    
077                    String jUsername = credentials[0];
078                    String jPassword = credentials[1];
079                    boolean encPassword = GetterUtil.getBoolean(credentials[2]);
080    
081                    if (Validator.isNull(jUsername) || Validator.isNull(jPassword)) {
082                            return null;
083                    }
084    
085                    try {
086                            long userId = GetterUtil.getLong(jUsername);
087    
088                            if (userId > 0) {
089                                    User user = UserLocalServiceUtil.getUserById(userId);
090    
091                                    if (user.isLockout()) {
092                                            return null;
093                                    }
094                                    else if (PropsValues.LIVE_USERS_ENABLED) {
095                                            UserTracker userTracker =
096                                                    UserTrackerLocalServiceUtil.fetchUserTracker(userId);
097    
098                                            if ((userTracker == null) &&
099                                                    (session.getAttribute(WebKeys.USER) == null)) {
100    
101                                                    session.invalidate();
102    
103                                                    return null;
104                                            }
105                                    }
106                            }
107                            else {
108                                    return null;
109                            }
110                    }
111                    catch (NoSuchUserException nsue) {
112                            return null;
113                    }
114    
115                    session.setAttribute("j_username", jUsername);
116    
117                    // Not having access to the unencrypted password will not allow you to
118                    // connect to external resources that require it (mail server)
119    
120                    if (encPassword) {
121                            session.setAttribute("j_password", jPassword);
122                    }
123                    else {
124                            session.setAttribute("j_password", PwdEncryptor.encrypt(jPassword));
125    
126                            if (PropsValues.SESSION_STORE_PASSWORD) {
127                                    session.setAttribute(WebKeys.USER_PASSWORD, jPassword);
128                            }
129                    }
130    
131                    session.setAttribute("j_remoteuser", jUsername);
132    
133                    if (PropsValues.PORTAL_JAAS_ENABLE) {
134                            response.sendRedirect(
135                                    PortalUtil.getPathMain() + "/portal/touch_protected");
136                    }
137    
138                    return jUsername;
139            }
140    
141            @Override
142            protected void processFilter(
143                            HttpServletRequest request, HttpServletResponse response,
144                            FilterChain filterChain)
145                    throws Exception {
146    
147                    HttpSession session = request.getSession();
148    
149                    String host = PortalUtil.getHost(request);
150    
151                    if (PortalInstances.isAutoLoginIgnoreHost(host)) {
152                            if (_log.isDebugEnabled()) {
153                                    _log.debug("Ignore host " + host);
154                            }
155    
156                            processFilter(
157                                    AutoLoginFilter.class, request, response, filterChain);
158    
159                            return;
160                    }
161    
162                    String contextPath = PortalUtil.getPathContext();
163    
164                    String path = request.getRequestURI().toLowerCase();
165    
166                    if (!contextPath.equals(StringPool.SLASH) &&
167                            (path.indexOf(contextPath) != -1)) {
168    
169                            path = path.substring(contextPath.length());
170                    }
171    
172                    if (PortalInstances.isAutoLoginIgnorePath(path)) {
173                            if (_log.isDebugEnabled()) {
174                                    _log.debug("Ignore path " + path);
175                            }
176    
177                            processFilter(
178                                    AutoLoginFilter.class, request, response, filterChain);
179    
180                            return;
181                    }
182    
183                    String remoteUser = request.getRemoteUser();
184                    String jUserName = (String)session.getAttribute("j_username");
185    
186                    if (!PropsValues.AUTH_LOGIN_DISABLED &&
187                            (remoteUser == null) && (jUserName == null)) {
188    
189                            for (AutoLogin autoLogin : _autoLogins) {
190                                    try {
191                                            String[] credentials = autoLogin.login(request, response);
192    
193                                            String redirect = (String)request.getAttribute(
194                                                    AutoLogin.AUTO_LOGIN_REDIRECT);
195    
196                                            if (Validator.isNotNull(redirect)) {
197                                                    response.sendRedirect(redirect);
198    
199                                                    return;
200                                            }
201    
202                                            String loginRemoteUser = getLoginRemoteUser(
203                                                    request, response, session, credentials);
204    
205                                            if (loginRemoteUser != null) {
206                                                    request = new ProtectedServletRequest(
207                                                            request, loginRemoteUser);
208    
209                                                    if (PropsValues.PORTAL_JAAS_ENABLE) {
210                                                            return;
211                                                    }
212    
213                                                    redirect = (String)request.getAttribute(
214                                                            AutoLogin.AUTO_LOGIN_REDIRECT_AND_CONTINUE);
215    
216                                                    if (Validator.isNotNull(redirect)) {
217                                                            response.sendRedirect(redirect);
218    
219                                                            break;
220                                                    }
221                                            }
222                                    }
223                                    catch (Exception e) {
224                                            if (_log.isWarnEnabled()) {
225                                                    _log.warn(e, e);
226                                            }
227    
228                                            String currentURL = PortalUtil.getCurrentURL(request);
229    
230                                            if (currentURL.endsWith(_PATH_CHAT_LATEST)) {
231                                                    if (_log.isWarnEnabled()) {
232                                                            _log.warn(
233                                                                    "Current URL " + currentURL +
234                                                                            " generates exception: " + e.getMessage());
235                                                    }
236                                            }
237                                            else {
238                                                    _log.error(
239                                                            "Current URL " + currentURL +
240                                                                    " generates exception: " + e.getMessage());
241                                            }
242                                    }
243                            }
244                    }
245    
246                    processFilter(AutoLoginFilter.class, request, response, filterChain);
247            }
248    
249            private static final String _PATH_CHAT_LATEST = "/-/chat/latest";
250    
251            private static Log _log = LogFactoryUtil.getLog(AutoLoginFilter.class);
252    
253            private static List<AutoLogin> _autoLogins =
254                    new CopyOnWriteArrayList<AutoLogin>();
255    
256    }