/modules/apps/archived/portal-security-sso-cas-impl/src/main/java/com/liferay/portal/security/sso/cas/internal/servlet/filter/CASFilter.java
Java | 296 lines | 186 code | 64 blank | 46 comment | 14 complexity | 57444e129188913aa7824a38f3983e1f MD5 | raw file
- /**
- * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 2.1 of the License, or (at your option)
- * any later version.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- */
- package com.liferay.portal.security.sso.cas.internal.servlet.filter;
- import com.liferay.portal.kernel.exception.PortalException;
- import com.liferay.portal.kernel.log.Log;
- import com.liferay.portal.kernel.log.LogFactoryUtil;
- import com.liferay.portal.kernel.module.configuration.ConfigurationProvider;
- import com.liferay.portal.kernel.servlet.BaseFilter;
- import com.liferay.portal.kernel.settings.CompanyServiceSettingsLocator;
- import com.liferay.portal.kernel.util.HashMapBuilder;
- import com.liferay.portal.kernel.util.HttpComponentsUtil;
- import com.liferay.portal.kernel.util.ParamUtil;
- import com.liferay.portal.kernel.util.Portal;
- import com.liferay.portal.kernel.util.Validator;
- import com.liferay.portal.security.sso.cas.configuration.CASConfiguration;
- import com.liferay.portal.security.sso.cas.constants.CASConstants;
- import com.liferay.portal.security.sso.cas.internal.constants.CASWebKeys;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import org.jasig.cas.client.authentication.AttributePrincipal;
- import org.jasig.cas.client.util.CommonUtils;
- import org.jasig.cas.client.validation.Assertion;
- import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
- import org.jasig.cas.client.validation.TicketValidationException;
- import org.jasig.cas.client.validation.TicketValidator;
- import org.osgi.service.component.annotations.Component;
- import org.osgi.service.component.annotations.Reference;
- /**
- * Participates in every login and logout that triggers an HTTP request to
- * Liferay Portal.
- *
- * <p>
- * This class checks if the HTTP session attribute <code>CAS_FORCE_LOGOUT</code>
- * is set by CASAutoLogin and, if so, redirects the browser to the configured
- * CAS Logout URL.
- * </p>
- *
- * <p>
- * Next, if the session attribute <code>CAS_LOGIN</code> has not already been
- * set and no ticket parameter is received via the HTTP servlet request, the CAS
- * server login URL is constructed based on the configuration of the Login URL,
- * the Server name, and the Service URL and the browser is redirected to this
- * URL. If a ticket parameter was received, it will be validated.
- * </p>
- *
- * <p>
- * Validation includes sending a SAML request containing the ticket to the CAS
- * server, and in return receiving an assertion of user attributes. However,
- * only the principal attribute is used and it is set as the session attribute
- * <code>CAS_LOGIN</code> as mentioned earlier. It is important that the CAS
- * server issues a principal of the same type that the portal instance is
- * configured to use (e.g., screen name versus email address).
- * </p>
- *
- * @author Michael Young
- * @author Brian Wing Shun Chan
- * @author Raymond Augé
- * @author Tina Tian
- * @author Zsolt Balogh
- */
- @Component(
- configurationPid = "com.liferay.portal.security.sso.cas.configuration.CASConfiguration",
- immediate = true,
- property = {
- "before-filter=Auto Login Filter", "dispatcher=FORWARD",
- "dispatcher=REQUEST", "servlet-context-name=",
- "servlet-filter-name=SSO CAS Filter", "url-pattern=/c/portal/login",
- "url-pattern=/c/portal/logout"
- },
- service = Filter.class
- )
- public class CASFilter extends BaseFilter {
- public static void reload(long companyId) {
- _ticketValidators.remove(companyId);
- }
- @Override
- public boolean isFilterEnabled(
- HttpServletRequest httpServletRequest,
- HttpServletResponse httpServletResponse) {
- try {
- CASConfiguration casConfiguration =
- _configurationProvider.getConfiguration(
- CASConfiguration.class,
- new CompanyServiceSettingsLocator(
- _portal.getCompanyId(httpServletRequest),
- CASConstants.SERVICE_NAME));
- if (casConfiguration.enabled()) {
- return true;
- }
- }
- catch (Exception exception) {
- _log.error(exception);
- }
- return false;
- }
- @Override
- protected Log getLog() {
- return _log;
- }
- @Override
- protected void processFilter(
- HttpServletRequest httpServletRequest,
- HttpServletResponse httpServletResponse, FilterChain filterChain)
- throws Exception {
- HttpSession httpSession = httpServletRequest.getSession();
- long companyId = _portal.getCompanyId(httpServletRequest);
- CASConfiguration casConfiguration =
- _configurationProvider.getConfiguration(
- CASConfiguration.class,
- new CompanyServiceSettingsLocator(
- companyId, CASConstants.SERVICE_NAME));
- Object forceLogout = httpSession.getAttribute(
- CASWebKeys.CAS_FORCE_LOGOUT);
- if (forceLogout != null) {
- httpSession.removeAttribute(CASWebKeys.CAS_FORCE_LOGOUT);
- String logoutUrl = casConfiguration.logoutURL();
- httpServletResponse.sendRedirect(logoutUrl);
- return;
- }
- String pathInfo = httpServletRequest.getPathInfo();
- if (Validator.isNotNull(pathInfo) &&
- pathInfo.contains("/portal/logout")) {
- httpSession.invalidate();
- String logoutUrl = casConfiguration.logoutURL();
- httpServletResponse.sendRedirect(logoutUrl);
- return;
- }
- String login = (String)httpSession.getAttribute(CASWebKeys.CAS_LOGIN);
- if (Validator.isNotNull(login)) {
- processFilter(
- CASFilter.class.getName(), httpServletRequest,
- httpServletResponse, filterChain);
- return;
- }
- String serverName = casConfiguration.serverName();
- String serviceURL = casConfiguration.serviceURL();
- if (Validator.isNull(serviceURL)) {
- serviceURL = CommonUtils.constructServiceUrl(
- httpServletRequest, httpServletResponse, serviceURL, serverName,
- "service", "ticket", true);
- }
- String ticket = ParamUtil.getString(httpServletRequest, "ticket");
- if (Validator.isNull(ticket)) {
- String loginUrl = casConfiguration.loginURL();
- loginUrl = HttpComponentsUtil.addParameter(
- loginUrl, "service", serviceURL);
- httpServletResponse.sendRedirect(loginUrl);
- return;
- }
- TicketValidator ticketValidator = _getTicketValidator(companyId);
- Assertion assertion = null;
- try {
- assertion = ticketValidator.validate(ticket, serviceURL);
- }
- catch (TicketValidationException ticketValidationException) {
- if (_log.isDebugEnabled()) {
- _log.debug(ticketValidationException);
- }
- else if (_log.isInfoEnabled()) {
- _log.info(ticketValidationException);
- }
- _portal.sendError(
- new PortalException(
- "Unable to validate CAS ticket: " + ticket,
- ticketValidationException),
- httpServletRequest, httpServletResponse);
- return;
- }
- if (assertion != null) {
- AttributePrincipal attributePrincipal = assertion.getPrincipal();
- login = attributePrincipal.getName();
- httpSession.setAttribute(CASWebKeys.CAS_LOGIN, login);
- }
- processFilter(
- CASFilter.class.getName(), httpServletRequest, httpServletResponse,
- filterChain);
- }
- @Reference(unbind = "-")
- protected void setConfigurationProvider(
- ConfigurationProvider configurationProvider) {
- _configurationProvider = configurationProvider;
- }
- private TicketValidator _getTicketValidator(long companyId)
- throws Exception {
- TicketValidator ticketValidator = _ticketValidators.get(companyId);
- if (ticketValidator != null) {
- return ticketValidator;
- }
- CASConfiguration casConfiguration =
- _configurationProvider.getConfiguration(
- CASConfiguration.class,
- new CompanyServiceSettingsLocator(
- companyId, CASConstants.SERVICE_NAME));
- String serverUrl = casConfiguration.serverURL();
- Cas20ProxyTicketValidator cas20ProxyTicketValidator =
- new Cas20ProxyTicketValidator(serverUrl);
- cas20ProxyTicketValidator.setCustomParameters(
- HashMapBuilder.put(
- "casServerLoginUrl", casConfiguration.loginURL()
- ).put(
- "casServerUrlPrefix", serverUrl
- ).put(
- "redirectAfterValidation", "false"
- ).put(
- "serverName", casConfiguration.serverName()
- ).build());
- _ticketValidators.put(companyId, cas20ProxyTicketValidator);
- return cas20ProxyTicketValidator;
- }
- private static final Log _log = LogFactoryUtil.getLog(CASFilter.class);
- private static final Map<Long, TicketValidator> _ticketValidators =
- new ConcurrentHashMap<>();
- private ConfigurationProvider _configurationProvider;
- @Reference
- private Portal _portal;
- }