/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.security.mvc; import java.io.IOException; import java.net.URL; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apereo.portal.security.IPerson; import org.apereo.portal.security.IPersonManager; import org.apereo.portal.url.IPortalUrlBuilder; import org.apereo.portal.url.IPortalUrlProvider; import org.apereo.portal.url.UrlType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * Controller to work with the local login form. The form presented by the login portlet is * typically used to generate the post to this servlet. Actual login processing occurs in * PortalPreAuthenticatedProcessingFilter. * */ @Controller @RequestMapping("/Login") public class LoginController { public static final String REFERER_URL_PARAM = "refUrl"; public static final String AUTH_ATTEMPTED_KEY = "up_authenticationAttempted"; public static final String AUTH_ERROR_KEY = "up_authenticationError"; public static final String ATTEMPTED_USERNAME_KEY = "up_attemptedUserName"; public static final String REQUESTED_PROFILE_KEY = "profile"; protected final Log log = LogFactory.getLog(getClass()); protected final Log swapperLog = LogFactory.getLog("org.apereo.portal.portlets.swapper"); private IPortalUrlProvider portalUrlProvider; private IPersonManager personManager; @Autowired public void setPersonManager(IPersonManager personManager) { this.personManager = personManager; } @Autowired public void setPortalUrlProvider(IPortalUrlProvider portalUrlProvider) { this.portalUrlProvider = portalUrlProvider; } /** * Process the incoming HttpServletRequest. Note that this processing occurs after * PortalPreAuthenticatedProcessingFilter has run and performed pre-processing. * * @param request * @param response * @exception ServletException * @exception IOException */ @RequestMapping public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); // create the redirect URL, adding fname and args parameters if necessary String redirectTarget = null; final String refUrl = request.getParameter(REFERER_URL_PARAM); final URL redirectLocation = parseLocalRefUrl(request, refUrl); if (redirectLocation != null) { redirectTarget = redirectLocation.toString(); } if (redirectTarget == null) { /* Grab the target functional name, if any, off the login request. * Also any arguments for the target. We will pass them along after authentication. */ String targetFname = request.getParameter("uP_fname"); if (targetFname == null) { final IPortalUrlBuilder defaultUrl = this.portalUrlProvider.getDefaultUrl(request); redirectTarget = defaultUrl.getUrlString(); } else { try { final IPortalUrlBuilder urlBuilder = this.portalUrlProvider.getPortalUrlBuilderByPortletFName( request, targetFname, UrlType.RENDER); Enumeration<String> e = request.getParameterNames(); while (e.hasMoreElements()) { String paramName = e.nextElement(); if (!paramName.equals("uP_fname")) { urlBuilder.addParameter( paramName, request.getParameterValues(paramName)); } } redirectTarget = urlBuilder.getUrlString(); } catch (IllegalArgumentException e) { final IPortalUrlBuilder defaultUrl = this.portalUrlProvider.getDefaultUrl(request); redirectTarget = defaultUrl.getUrlString(); } } } IPerson person = null; final Object authError = request.getSession(false).getAttribute(LoginController.AUTH_ERROR_KEY); if (authError == null || !((Boolean) authError)) { person = this.personManager.getPerson(request); } if (person == null || !person.getSecurityContext().isAuthenticated()) { if (request.getMethod().equals("POST")) request.getSession(false).setAttribute(AUTH_ATTEMPTED_KEY, "true"); // Preserve the attempted username so it can be redisplayed to the user String attemptedUserName = request.getParameter("userName"); if (attemptedUserName != null) request.getSession(false) .setAttribute(ATTEMPTED_USERNAME_KEY, request.getParameter("userName")); } final String encodedRedirectURL = response.encodeRedirectURL(redirectTarget); if (log.isDebugEnabled()) { log.debug("Redirecting to " + redirectTarget); } response.sendRedirect(encodedRedirectURL); } /** * Analyzes the <code>refUrl</code> parameter, if any, and attempts to produce a local (same * protocol, host, and port) URL based on it. * * @param request The current {@link HttpServletRequest} * @param refUrl The <code>refUrl</code> parameter passed on the querry string * @return A valid local {@link URL} or null */ /* package-private */ URL parseLocalRefUrl( final HttpServletRequest request, final String refUrl) { URL rslt = null; // default if (StringUtils.isNotBlank(refUrl)) { try { final URL context = new URL(request.getRequestURL().toString()); final URL location = new URL(context, refUrl); if (location.getProtocol().equals(context.getProtocol()) && location.getHost().equals(context.getHost()) && location.getPort() == context.getPort()) { rslt = location; } else { log.warn("The specified refUrl is not local: " + refUrl); } } catch (Exception e) { log.warn("Unable to analyze specified refUrl: " + refUrl); log.debug(e); } } return rslt; } }