PageRenderTime 60ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/apps/archived/portal-security-sso-cas-impl/src/main/java/com/liferay/portal/security/sso/cas/internal/servlet/filter/CASFilter.java

https://github.com/danielreuther/liferay-portal
Java | 296 lines | 186 code | 64 blank | 46 comment | 14 complexity | 57444e129188913aa7824a38f3983e1f MD5 | raw file
  1. /**
  2. * Copyright (c) 2000-present 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. package com.liferay.portal.security.sso.cas.internal.servlet.filter;
  15. import com.liferay.portal.kernel.exception.PortalException;
  16. import com.liferay.portal.kernel.log.Log;
  17. import com.liferay.portal.kernel.log.LogFactoryUtil;
  18. import com.liferay.portal.kernel.module.configuration.ConfigurationProvider;
  19. import com.liferay.portal.kernel.servlet.BaseFilter;
  20. import com.liferay.portal.kernel.settings.CompanyServiceSettingsLocator;
  21. import com.liferay.portal.kernel.util.HashMapBuilder;
  22. import com.liferay.portal.kernel.util.HttpComponentsUtil;
  23. import com.liferay.portal.kernel.util.ParamUtil;
  24. import com.liferay.portal.kernel.util.Portal;
  25. import com.liferay.portal.kernel.util.Validator;
  26. import com.liferay.portal.security.sso.cas.configuration.CASConfiguration;
  27. import com.liferay.portal.security.sso.cas.constants.CASConstants;
  28. import com.liferay.portal.security.sso.cas.internal.constants.CASWebKeys;
  29. import java.util.Map;
  30. import java.util.concurrent.ConcurrentHashMap;
  31. import javax.servlet.Filter;
  32. import javax.servlet.FilterChain;
  33. import javax.servlet.http.HttpServletRequest;
  34. import javax.servlet.http.HttpServletResponse;
  35. import javax.servlet.http.HttpSession;
  36. import org.jasig.cas.client.authentication.AttributePrincipal;
  37. import org.jasig.cas.client.util.CommonUtils;
  38. import org.jasig.cas.client.validation.Assertion;
  39. import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
  40. import org.jasig.cas.client.validation.TicketValidationException;
  41. import org.jasig.cas.client.validation.TicketValidator;
  42. import org.osgi.service.component.annotations.Component;
  43. import org.osgi.service.component.annotations.Reference;
  44. /**
  45. * Participates in every login and logout that triggers an HTTP request to
  46. * Liferay Portal.
  47. *
  48. * <p>
  49. * This class checks if the HTTP session attribute <code>CAS_FORCE_LOGOUT</code>
  50. * is set by CASAutoLogin and, if so, redirects the browser to the configured
  51. * CAS Logout URL.
  52. * </p>
  53. *
  54. * <p>
  55. * Next, if the session attribute <code>CAS_LOGIN</code> has not already been
  56. * set and no ticket parameter is received via the HTTP servlet request, the CAS
  57. * server login URL is constructed based on the configuration of the Login URL,
  58. * the Server name, and the Service URL and the browser is redirected to this
  59. * URL. If a ticket parameter was received, it will be validated.
  60. * </p>
  61. *
  62. * <p>
  63. * Validation includes sending a SAML request containing the ticket to the CAS
  64. * server, and in return receiving an assertion of user attributes. However,
  65. * only the principal attribute is used and it is set as the session attribute
  66. * <code>CAS_LOGIN</code> as mentioned earlier. It is important that the CAS
  67. * server issues a principal of the same type that the portal instance is
  68. * configured to use (e.g., screen name versus email address).
  69. * </p>
  70. *
  71. * @author Michael Young
  72. * @author Brian Wing Shun Chan
  73. * @author Raymond Augé
  74. * @author Tina Tian
  75. * @author Zsolt Balogh
  76. */
  77. @Component(
  78. configurationPid = "com.liferay.portal.security.sso.cas.configuration.CASConfiguration",
  79. immediate = true,
  80. property = {
  81. "before-filter=Auto Login Filter", "dispatcher=FORWARD",
  82. "dispatcher=REQUEST", "servlet-context-name=",
  83. "servlet-filter-name=SSO CAS Filter", "url-pattern=/c/portal/login",
  84. "url-pattern=/c/portal/logout"
  85. },
  86. service = Filter.class
  87. )
  88. public class CASFilter extends BaseFilter {
  89. public static void reload(long companyId) {
  90. _ticketValidators.remove(companyId);
  91. }
  92. @Override
  93. public boolean isFilterEnabled(
  94. HttpServletRequest httpServletRequest,
  95. HttpServletResponse httpServletResponse) {
  96. try {
  97. CASConfiguration casConfiguration =
  98. _configurationProvider.getConfiguration(
  99. CASConfiguration.class,
  100. new CompanyServiceSettingsLocator(
  101. _portal.getCompanyId(httpServletRequest),
  102. CASConstants.SERVICE_NAME));
  103. if (casConfiguration.enabled()) {
  104. return true;
  105. }
  106. }
  107. catch (Exception exception) {
  108. _log.error(exception);
  109. }
  110. return false;
  111. }
  112. @Override
  113. protected Log getLog() {
  114. return _log;
  115. }
  116. @Override
  117. protected void processFilter(
  118. HttpServletRequest httpServletRequest,
  119. HttpServletResponse httpServletResponse, FilterChain filterChain)
  120. throws Exception {
  121. HttpSession httpSession = httpServletRequest.getSession();
  122. long companyId = _portal.getCompanyId(httpServletRequest);
  123. CASConfiguration casConfiguration =
  124. _configurationProvider.getConfiguration(
  125. CASConfiguration.class,
  126. new CompanyServiceSettingsLocator(
  127. companyId, CASConstants.SERVICE_NAME));
  128. Object forceLogout = httpSession.getAttribute(
  129. CASWebKeys.CAS_FORCE_LOGOUT);
  130. if (forceLogout != null) {
  131. httpSession.removeAttribute(CASWebKeys.CAS_FORCE_LOGOUT);
  132. String logoutUrl = casConfiguration.logoutURL();
  133. httpServletResponse.sendRedirect(logoutUrl);
  134. return;
  135. }
  136. String pathInfo = httpServletRequest.getPathInfo();
  137. if (Validator.isNotNull(pathInfo) &&
  138. pathInfo.contains("/portal/logout")) {
  139. httpSession.invalidate();
  140. String logoutUrl = casConfiguration.logoutURL();
  141. httpServletResponse.sendRedirect(logoutUrl);
  142. return;
  143. }
  144. String login = (String)httpSession.getAttribute(CASWebKeys.CAS_LOGIN);
  145. if (Validator.isNotNull(login)) {
  146. processFilter(
  147. CASFilter.class.getName(), httpServletRequest,
  148. httpServletResponse, filterChain);
  149. return;
  150. }
  151. String serverName = casConfiguration.serverName();
  152. String serviceURL = casConfiguration.serviceURL();
  153. if (Validator.isNull(serviceURL)) {
  154. serviceURL = CommonUtils.constructServiceUrl(
  155. httpServletRequest, httpServletResponse, serviceURL, serverName,
  156. "service", "ticket", true);
  157. }
  158. String ticket = ParamUtil.getString(httpServletRequest, "ticket");
  159. if (Validator.isNull(ticket)) {
  160. String loginUrl = casConfiguration.loginURL();
  161. loginUrl = HttpComponentsUtil.addParameter(
  162. loginUrl, "service", serviceURL);
  163. httpServletResponse.sendRedirect(loginUrl);
  164. return;
  165. }
  166. TicketValidator ticketValidator = _getTicketValidator(companyId);
  167. Assertion assertion = null;
  168. try {
  169. assertion = ticketValidator.validate(ticket, serviceURL);
  170. }
  171. catch (TicketValidationException ticketValidationException) {
  172. if (_log.isDebugEnabled()) {
  173. _log.debug(ticketValidationException);
  174. }
  175. else if (_log.isInfoEnabled()) {
  176. _log.info(ticketValidationException);
  177. }
  178. _portal.sendError(
  179. new PortalException(
  180. "Unable to validate CAS ticket: " + ticket,
  181. ticketValidationException),
  182. httpServletRequest, httpServletResponse);
  183. return;
  184. }
  185. if (assertion != null) {
  186. AttributePrincipal attributePrincipal = assertion.getPrincipal();
  187. login = attributePrincipal.getName();
  188. httpSession.setAttribute(CASWebKeys.CAS_LOGIN, login);
  189. }
  190. processFilter(
  191. CASFilter.class.getName(), httpServletRequest, httpServletResponse,
  192. filterChain);
  193. }
  194. @Reference(unbind = "-")
  195. protected void setConfigurationProvider(
  196. ConfigurationProvider configurationProvider) {
  197. _configurationProvider = configurationProvider;
  198. }
  199. private TicketValidator _getTicketValidator(long companyId)
  200. throws Exception {
  201. TicketValidator ticketValidator = _ticketValidators.get(companyId);
  202. if (ticketValidator != null) {
  203. return ticketValidator;
  204. }
  205. CASConfiguration casConfiguration =
  206. _configurationProvider.getConfiguration(
  207. CASConfiguration.class,
  208. new CompanyServiceSettingsLocator(
  209. companyId, CASConstants.SERVICE_NAME));
  210. String serverUrl = casConfiguration.serverURL();
  211. Cas20ProxyTicketValidator cas20ProxyTicketValidator =
  212. new Cas20ProxyTicketValidator(serverUrl);
  213. cas20ProxyTicketValidator.setCustomParameters(
  214. HashMapBuilder.put(
  215. "casServerLoginUrl", casConfiguration.loginURL()
  216. ).put(
  217. "casServerUrlPrefix", serverUrl
  218. ).put(
  219. "redirectAfterValidation", "false"
  220. ).put(
  221. "serverName", casConfiguration.serverName()
  222. ).build());
  223. _ticketValidators.put(companyId, cas20ProxyTicketValidator);
  224. return cas20ProxyTicketValidator;
  225. }
  226. private static final Log _log = LogFactoryUtil.getLog(CASFilter.class);
  227. private static final Map<Long, TicketValidator> _ticketValidators =
  228. new ConcurrentHashMap<>();
  229. private ConfigurationProvider _configurationProvider;
  230. @Reference
  231. private Portal _portal;
  232. }