001    /**
002     * Copyright (c) 2000-2013 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.sso.cas;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.HttpUtil;
020    import com.liferay.portal.kernel.util.ParamUtil;
021    import com.liferay.portal.kernel.util.PropsKeys;
022    import com.liferay.portal.kernel.util.Validator;
023    import com.liferay.portal.servlet.filters.BasePortalFilter;
024    import com.liferay.portal.util.PortalUtil;
025    import com.liferay.portal.util.PrefsPropsUtil;
026    import com.liferay.portal.util.PropsValues;
027    import com.liferay.portal.util.WebKeys;
028    
029    import java.util.HashMap;
030    import java.util.Map;
031    import java.util.concurrent.ConcurrentHashMap;
032    
033    import javax.servlet.FilterChain;
034    import javax.servlet.http.HttpServletRequest;
035    import javax.servlet.http.HttpServletResponse;
036    import javax.servlet.http.HttpSession;
037    
038    import org.jasig.cas.client.authentication.AttributePrincipal;
039    import org.jasig.cas.client.util.CommonUtils;
040    import org.jasig.cas.client.validation.Assertion;
041    import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
042    import org.jasig.cas.client.validation.TicketValidator;
043    
044    /**
045     * @author Michael Young
046     * @author Brian Wing Shun Chan
047     * @author Raymond Aug??
048     * @author Tina Tian
049     * @author Zsolt Balogh
050     */
051    public class CASFilter extends BasePortalFilter {
052    
053            public static void reload(long companyId) {
054                    _ticketValidators.remove(companyId);
055            }
056    
057            @Override
058            public boolean isFilterEnabled(
059                    HttpServletRequest request, HttpServletResponse response) {
060    
061                    try {
062                            long companyId = PortalUtil.getCompanyId(request);
063    
064                            if (PrefsPropsUtil.getBoolean(
065                                            companyId, PropsKeys.CAS_AUTH_ENABLED,
066                                            PropsValues.CAS_AUTH_ENABLED)) {
067    
068                                    return true;
069                            }
070                    }
071                    catch (Exception e) {
072                            _log.error(e, e);
073                    }
074    
075                    return false;
076            }
077    
078            @Override
079            protected Log getLog() {
080                    return _log;
081            }
082    
083            protected TicketValidator getTicketValidator(long companyId)
084                    throws Exception {
085    
086                    TicketValidator ticketValidator = _ticketValidators.get(companyId);
087    
088                    if (ticketValidator != null) {
089                            return ticketValidator;
090                    }
091    
092                    String serverName = PrefsPropsUtil.getString(
093                            companyId, PropsKeys.CAS_SERVER_NAME, PropsValues.CAS_SERVER_NAME);
094                    String serverUrl = PrefsPropsUtil.getString(
095                            companyId, PropsKeys.CAS_SERVER_URL, PropsValues.CAS_SERVER_URL);
096                    String loginUrl = PrefsPropsUtil.getString(
097                            companyId, PropsKeys.CAS_LOGIN_URL, PropsValues.CAS_LOGIN_URL);
098    
099                    Cas20ProxyTicketValidator cas20ProxyTicketValidator =
100                            new Cas20ProxyTicketValidator(serverUrl);
101    
102                    Map<String, String> parameters = new HashMap<String, String>();
103    
104                    parameters.put("serverName", serverName);
105                    parameters.put("casServerUrlPrefix", serverUrl);
106                    parameters.put("casServerLoginUrl", loginUrl);
107                    parameters.put("redirectAfterValidation", "false");
108    
109                    cas20ProxyTicketValidator.setCustomParameters(parameters);
110    
111                    _ticketValidators.put(companyId, cas20ProxyTicketValidator);
112    
113                    return cas20ProxyTicketValidator;
114            }
115    
116            @Override
117            protected void processFilter(
118                            HttpServletRequest request, HttpServletResponse response,
119                            FilterChain filterChain)
120                    throws Exception {
121    
122                    HttpSession session = request.getSession();
123    
124                    long companyId = PortalUtil.getCompanyId(request);
125    
126                    String pathInfo = request.getPathInfo();
127    
128                    Object forceLogout = session.getAttribute(WebKeys.CAS_FORCE_LOGOUT);
129    
130                    if (forceLogout != null) {
131                            session.removeAttribute(WebKeys.CAS_FORCE_LOGOUT);
132    
133                            String logoutUrl = PrefsPropsUtil.getString(
134                                    companyId, PropsKeys.CAS_LOGOUT_URL,
135                                    PropsValues.CAS_LOGOUT_URL);
136    
137                            response.sendRedirect(logoutUrl);
138    
139                            return;
140                    }
141    
142                    if (Validator.isNotNull(pathInfo) &&
143                            pathInfo.contains("/portal/logout")) {
144    
145                            session.invalidate();
146    
147                            String logoutUrl = PrefsPropsUtil.getString(
148                                    companyId, PropsKeys.CAS_LOGOUT_URL,
149                                    PropsValues.CAS_LOGOUT_URL);
150    
151                            response.sendRedirect(logoutUrl);
152    
153                            return;
154                    }
155                    else {
156                            String login = (String)session.getAttribute(WebKeys.CAS_LOGIN);
157    
158                            if (Validator.isNotNull(login)) {
159                                    processFilter(CASFilter.class, request, response, filterChain);
160    
161                                    return;
162                            }
163    
164                            String serverName = PrefsPropsUtil.getString(
165                                    companyId, PropsKeys.CAS_SERVER_NAME,
166                                    PropsValues.CAS_SERVER_NAME);
167    
168                            String serviceUrl = PrefsPropsUtil.getString(
169                                    companyId, PropsKeys.CAS_SERVICE_URL,
170                                    PropsValues.CAS_SERVICE_URL);
171    
172                            if (Validator.isNull(serviceUrl)) {
173                                    serviceUrl = CommonUtils.constructServiceUrl(
174                                            request, response, serviceUrl, serverName, "ticket", false);
175                            }
176    
177                            String ticket = ParamUtil.getString(request, "ticket");
178    
179                            if (Validator.isNull(ticket)) {
180                                    String loginUrl = PrefsPropsUtil.getString(
181                                            companyId, PropsKeys.CAS_LOGIN_URL,
182                                            PropsValues.CAS_LOGIN_URL);
183    
184                                    loginUrl = HttpUtil.addParameter(
185                                            loginUrl, "service", serviceUrl);
186    
187                                    response.sendRedirect(loginUrl);
188    
189                                    return;
190                            }
191    
192                            TicketValidator ticketValidator = getTicketValidator(companyId);
193    
194                            Assertion assertion = ticketValidator.validate(ticket, serviceUrl);
195    
196                            if (assertion != null) {
197                                    AttributePrincipal attributePrincipal =
198                                            assertion.getPrincipal();
199    
200                                    login = attributePrincipal.getName();
201    
202                                    session.setAttribute(WebKeys.CAS_LOGIN, login);
203                            }
204                    }
205    
206                    processFilter(CASFilter.class, request, response, filterChain);
207            }
208    
209            private static Log _log = LogFactoryUtil.getLog(CASFilter.class);
210    
211            private static Map<Long, TicketValidator> _ticketValidators =
212                    new ConcurrentHashMap<Long, TicketValidator>();
213    
214    }