001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.servlet.filters.secure;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.security.access.control.AccessControlUtil;
020    import com.liferay.portal.kernel.security.auth.http.HttpAuthManagerUtil;
021    import com.liferay.portal.kernel.security.auth.http.HttpAuthorizationHeader;
022    import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.Http;
025    import com.liferay.portal.kernel.util.HttpUtil;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.kernel.util.WebKeys;
031    import com.liferay.portal.model.User;
032    import com.liferay.portal.security.auth.CompanyThreadLocal;
033    import com.liferay.portal.security.auth.PrincipalThreadLocal;
034    import com.liferay.portal.security.permission.PermissionChecker;
035    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
036    import com.liferay.portal.security.permission.PermissionThreadLocal;
037    import com.liferay.portal.service.UserLocalServiceUtil;
038    import com.liferay.portal.servlet.filters.BasePortalFilter;
039    import com.liferay.portal.util.PortalUtil;
040    import com.liferay.portal.util.PropsUtil;
041    
042    import java.util.HashSet;
043    import java.util.Set;
044    
045    import javax.servlet.FilterChain;
046    import javax.servlet.FilterConfig;
047    import javax.servlet.http.HttpServletRequest;
048    import javax.servlet.http.HttpServletResponse;
049    import javax.servlet.http.HttpSession;
050    
051    /**
052     * @author Brian Wing Shun Chan
053     * @author Raymond Aug??
054     * @author Alexander Chow
055     */
056    public class SecureFilter extends BasePortalFilter {
057    
058            @Override
059            public void init(FilterConfig filterConfig) {
060                    super.init(filterConfig);
061    
062                    _basicAuthEnabled = GetterUtil.getBoolean(
063                            filterConfig.getInitParameter("basic_auth"));
064                    _digestAuthEnabled = GetterUtil.getBoolean(
065                            filterConfig.getInitParameter("digest_auth"));
066    
067                    String propertyPrefix = filterConfig.getInitParameter(
068                            "portal_property_prefix");
069    
070                    String[] hostsAllowed = null;
071    
072                    if (Validator.isNull(propertyPrefix)) {
073                            hostsAllowed = StringUtil.split(
074                                    filterConfig.getInitParameter("hosts.allowed"));
075                            _httpsRequired = GetterUtil.getBoolean(
076                                    filterConfig.getInitParameter("https.required"));
077                    }
078                    else {
079                            hostsAllowed = PropsUtil.getArray(propertyPrefix + "hosts.allowed");
080                            _httpsRequired = GetterUtil.getBoolean(
081                                    PropsUtil.get(propertyPrefix + "https.required"));
082                    }
083    
084                    for (String hostAllowed : hostsAllowed) {
085                            _hostsAllowed.add(hostAllowed);
086                    }
087    
088                    _usePermissionChecker = GetterUtil.getBoolean(
089                            filterConfig.getInitParameter("use_permission_checker"));
090            }
091    
092            protected HttpServletRequest basicAuth(
093                            HttpServletRequest request, HttpServletResponse response)
094                    throws Exception {
095    
096                    HttpSession session = request.getSession();
097    
098                    long userId = GetterUtil.getLong(
099                            (String)session.getAttribute(_AUTHENTICATED_USER));
100    
101                    if (userId > 0) {
102                            request = new ProtectedServletRequest(
103                                    request, String.valueOf(userId), HttpServletRequest.BASIC_AUTH);
104    
105                            initThreadLocals(request);
106                    }
107                    else {
108                            try {
109                                    userId = HttpAuthManagerUtil.getBasicUserId(request);
110                            }
111                            catch (Exception e) {
112                                    _log.error(e, e);
113                            }
114    
115                            if (userId > 0) {
116                                    request = setCredentials(
117                                            request, session, userId, HttpServletRequest.BASIC_AUTH);
118                            }
119                            else {
120                                    HttpAuthorizationHeader httpAuthorizationHeader =
121                                            new HttpAuthorizationHeader(
122                                                    HttpAuthorizationHeader.SCHEME_BASIC);
123    
124                                    HttpAuthManagerUtil.generateChallenge(
125                                            request, response, httpAuthorizationHeader);
126    
127                                    return null;
128                            }
129                    }
130    
131                    return request;
132            }
133    
134            protected HttpServletRequest digestAuth(
135                            HttpServletRequest request, HttpServletResponse response)
136                    throws Exception {
137    
138                    HttpSession session = request.getSession();
139    
140                    long userId = GetterUtil.getLong(
141                            (String)session.getAttribute(_AUTHENTICATED_USER));
142    
143                    if (userId > 0) {
144                            request = new ProtectedServletRequest(
145                                    request, String.valueOf(userId),
146                                    HttpServletRequest.DIGEST_AUTH);
147    
148                            initThreadLocals(request);
149                    }
150                    else {
151                            try {
152                                    userId = HttpAuthManagerUtil.getDigestUserId(request);
153                            }
154                            catch (Exception e) {
155                                    _log.error(e, e);
156                            }
157    
158                            if (userId > 0) {
159                                    request = setCredentials(
160                                            request, session, userId, HttpServletRequest.DIGEST_AUTH);
161                            }
162                            else {
163                                    HttpAuthorizationHeader httpAuthorizationHeader =
164                                            new HttpAuthorizationHeader(
165                                                    HttpAuthorizationHeader.SCHEME_DIGEST);
166    
167                                    HttpAuthManagerUtil.generateChallenge(
168                                            request, response, httpAuthorizationHeader);
169    
170                                    return null;
171                            }
172                    }
173    
174                    return request;
175            }
176    
177            protected void initThreadLocals(HttpServletRequest request)
178                    throws Exception {
179    
180                    HttpSession session = request.getSession();
181    
182                    User user = (User)session.getAttribute(WebKeys.USER);
183    
184                    initThreadLocals(user);
185    
186                    PrincipalThreadLocal.setPassword(PortalUtil.getUserPassword(request));
187            }
188    
189            protected void initThreadLocals(User user) throws Exception {
190                    CompanyThreadLocal.setCompanyId(user.getCompanyId());
191    
192                    PrincipalThreadLocal.setName(user.getUserId());
193    
194                    if (!_usePermissionChecker) {
195                            return;
196                    }
197    
198                    PermissionChecker permissionChecker =
199                            PermissionThreadLocal.getPermissionChecker();
200    
201                    if (permissionChecker != null) {
202                            return;
203                    }
204    
205                    permissionChecker = PermissionCheckerFactoryUtil.create(user);
206    
207                    PermissionThreadLocal.setPermissionChecker(permissionChecker);
208            }
209    
210            @Override
211            protected void processFilter(
212                            HttpServletRequest request, HttpServletResponse response,
213                            FilterChain filterChain)
214                    throws Exception {
215    
216                    String remoteAddr = request.getRemoteAddr();
217    
218                    if (AccessControlUtil.isAccessAllowed(request, _hostsAllowed)) {
219                            if (_log.isDebugEnabled()) {
220                                    _log.debug("Access allowed for " + remoteAddr);
221                            }
222                    }
223                    else {
224                            if (_log.isWarnEnabled()) {
225                                    _log.warn("Access denied for " + remoteAddr);
226                            }
227    
228                            response.sendError(
229                                    HttpServletResponse.SC_FORBIDDEN,
230                                    "Access denied for " + remoteAddr);
231    
232                            return;
233                    }
234    
235                    if (_log.isDebugEnabled()) {
236                            if (_httpsRequired) {
237                                    _log.debug("https is required");
238                            }
239                            else {
240                                    _log.debug("https is not required");
241                            }
242                    }
243    
244                    if (_httpsRequired && !request.isSecure()) {
245                            if (_log.isDebugEnabled()) {
246                                    String completeURL = HttpUtil.getCompleteURL(request);
247    
248                                    _log.debug("Securing " + completeURL);
249                            }
250    
251                            StringBundler redirectURL = new StringBundler(5);
252    
253                            redirectURL.append(Http.HTTPS_WITH_SLASH);
254                            redirectURL.append(request.getServerName());
255                            redirectURL.append(request.getServletPath());
256    
257                            String queryString = request.getQueryString();
258    
259                            if (Validator.isNotNull(queryString)) {
260                                    redirectURL.append(StringPool.QUESTION);
261                                    redirectURL.append(request.getQueryString());
262                            }
263    
264                            if (_log.isDebugEnabled()) {
265                                    _log.debug("Redirect to " + redirectURL);
266                            }
267    
268                            response.sendRedirect(redirectURL.toString());
269                    }
270                    else {
271                            if (_log.isDebugEnabled()) {
272                                    String completeURL = HttpUtil.getCompleteURL(request);
273    
274                                    _log.debug("Not securing " + completeURL);
275                            }
276    
277                            User user = PortalUtil.getUser(request);
278    
279                            if (user == null) {
280                                    user = PortalUtil.initUser(request);
281                            }
282    
283                            initThreadLocals(user);
284    
285                            if (!user.isDefaultUser()) {
286                                    request = setCredentials(
287                                            request, request.getSession(), user.getUserId(), null);
288                            }
289                            else {
290                                    if (_digestAuthEnabled) {
291                                            request = digestAuth(request, response);
292                                    }
293                                    else if (_basicAuthEnabled) {
294                                            request = basicAuth(request, response);
295                                    }
296                            }
297    
298                            if (request != null) {
299                                    Class<?> clazz = getClass();
300    
301                                    processFilter(clazz.getName(), request, response, filterChain);
302                            }
303                    }
304            }
305    
306            protected HttpServletRequest setCredentials(
307                            HttpServletRequest request, HttpSession session, long userId,
308                            String authType)
309                    throws Exception {
310    
311                    User user = UserLocalServiceUtil.getUser(userId);
312    
313                    String userIdString = String.valueOf(userId);
314    
315                    request = new ProtectedServletRequest(request, userIdString, authType);
316    
317                    session.setAttribute(WebKeys.USER, user);
318                    session.setAttribute(_AUTHENTICATED_USER, userIdString);
319    
320                    initThreadLocals(request);
321    
322                    return request;
323            }
324    
325            protected void setUsePermissionChecker(boolean usePermissionChecker) {
326                    _usePermissionChecker = usePermissionChecker;
327            }
328    
329            private static final String _AUTHENTICATED_USER =
330                    SecureFilter.class + "_AUTHENTICATED_USER";
331    
332            private static final Log _log = LogFactoryUtil.getLog(SecureFilter.class);
333    
334            private boolean _basicAuthEnabled;
335            private boolean _digestAuthEnabled;
336            private final Set<String> _hostsAllowed = new HashSet<>();
337            private boolean _httpsRequired;
338            private boolean _usePermissionChecker;
339    
340    }