Coverage Report - org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint
 
Classes in this File Line Coverage Branch Coverage Complexity
AuthenticationProcessingFilterEntryPoint
78% 
77% 
1.846
 
 1  
 /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 2  
  *
 3  
  * Licensed under the Apache License, Version 2.0 (the "License");
 4  
  * you may not use this file except in compliance with the License.
 5  
  * You may obtain a copy of the License at
 6  
  *
 7  
  *     http://www.apache.org/licenses/LICENSE-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing, software
 10  
  * distributed under the License is distributed on an "AS IS" BASIS,
 11  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
  * See the License for the specific language governing permissions and
 13  
  * limitations under the License.
 14  
  */
 15  
 
 16  
 package org.acegisecurity.ui.webapp;
 17  
 
 18  
 import org.acegisecurity.AuthenticationException;
 19  
 
 20  
 import org.acegisecurity.ui.AuthenticationEntryPoint;
 21  
 
 22  
 import org.acegisecurity.util.PortMapper;
 23  
 import org.acegisecurity.util.PortMapperImpl;
 24  
 import org.acegisecurity.util.PortResolver;
 25  
 import org.acegisecurity.util.PortResolverImpl;
 26  
 
 27  
 import org.apache.commons.logging.Log;
 28  
 import org.apache.commons.logging.LogFactory;
 29  
 
 30  
 import org.springframework.beans.factory.InitializingBean;
 31  
 
 32  
 import org.springframework.util.Assert;
 33  
 
 34  
 import java.io.IOException;
 35  
 
 36  
 import javax.servlet.RequestDispatcher;
 37  
 import javax.servlet.ServletException;
 38  
 import javax.servlet.ServletRequest;
 39  
 import javax.servlet.ServletResponse;
 40  
 import javax.servlet.http.HttpServletRequest;
 41  
 import javax.servlet.http.HttpServletResponse;
 42  
 
 43  
 /**
 44  
  * <p>
 45  
  * Used by the <code>SecurityEnforcementFilter</code> to commence
 46  
  * authentication via the {@link AuthenticationProcessingFilter}. This object
 47  
  * holds the location of the login form, relative to the web app context path,
 48  
  * and is used to commence a redirect to that form.
 49  
  * </p>
 50  
  * <p>
 51  
  * By setting the <em>forceHttps</em> property to true, you may configure the
 52  
  * class to force the protocol used for the login form to be <code>HTTPS</code>,
 53  
  * even if the original intercepted request for a resource used the
 54  
  * <code>HTTP</code> protocol. When this happens, after a successful login
 55  
  * (via HTTPS), the original resource will still be accessed as HTTP, via the
 56  
  * original request URL. For the forced HTTPS feature to work, the {@link
 57  
  * PortMapper} is consulted to determine the HTTP:HTTPS pairs.
 58  
  * </p>
 59  
  * 
 60  
  * @author Ben Alex
 61  
  * @author colin sampaleanu
 62  
  * @author Omri Spector
 63  
  * @version $Id: AuthenticationProcessingFilterEntryPoint.java 1873 2007-05-25
 64  
  * 03:21:17Z benalex $
 65  
  */
 66  9
 public class AuthenticationProcessingFilterEntryPoint implements AuthenticationEntryPoint, InitializingBean {
 67  
         // ~ Static fields/initializers
 68  
         // =====================================================================================
 69  
 
 70  2
         private static final Log logger = LogFactory.getLog(AuthenticationProcessingFilterEntryPoint.class);
 71  
 
 72  
         // ~ Instance fields
 73  
         // ================================================================================================
 74  
 
 75  9
         private PortMapper portMapper = new PortMapperImpl();
 76  
 
 77  9
         private PortResolver portResolver = new PortResolverImpl();
 78  
 
 79  
         private String loginFormUrl;
 80  
 
 81  9
         private boolean forceHttps = false;
 82  
 
 83  9
         private boolean serverSideRedirect = false;
 84  
 
 85  
         // ~ Methods
 86  
         // ========================================================================================================
 87  
 
 88  
         public void afterPropertiesSet() throws Exception {
 89  10
                 Assert.hasLength(loginFormUrl, "loginFormUrl must be specified");
 90  9
                 Assert.notNull(portMapper, "portMapper must be specified");
 91  8
                 Assert.notNull(portResolver, "portResolver must be specified");
 92  7
         }
 93  
 
 94  
         /**
 95  
          * Allows subclasses to modify the login form URL that should be applicable
 96  
          * for a given request.
 97  
          * 
 98  
          * @param request the request
 99  
          * @param response the response
 100  
          * @param exception the exception
 101  
          * @return the URL (cannot be null or empty; defaults to
 102  
          * {@link #getLoginFormUrl()})
 103  
          */
 104  
         protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,
 105  
                         AuthenticationException exception) {
 106  8
                 return getLoginFormUrl();
 107  
         }
 108  
 
 109  
         public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException)
 110  
                         throws IOException, ServletException {
 111  8
                 HttpServletRequest req = (HttpServletRequest) request;
 112  8
                 HttpServletResponse resp = (HttpServletResponse) response;
 113  8
                 String scheme = request.getScheme();
 114  8
                 String serverName = request.getServerName();
 115  8
                 int serverPort = portResolver.getServerPort(request);
 116  8
                 String contextPath = req.getContextPath();
 117  
 
 118  8
                 boolean inHttp = "http".equals(scheme.toLowerCase());
 119  8
                 boolean inHttps = "https".equals(scheme.toLowerCase());
 120  
 
 121  8
                 boolean includePort = true;
 122  
 
 123  8
                 String redirectUrl = null;
 124  8
                 boolean doForceHttps = false;
 125  8
                 Integer httpsPort = null;
 126  
 
 127  8
                 if (inHttp && (serverPort == 80)) {
 128  2
                         includePort = false;
 129  
                 }
 130  6
                 else if (inHttps && (serverPort == 443)) {
 131  1
                         includePort = false;
 132  
                 }
 133  
 
 134  8
                 if (forceHttps && inHttp) {
 135  5
                         httpsPort = (Integer) portMapper.lookupHttpsPort(new Integer(serverPort));
 136  
 
 137  5
                         if (httpsPort != null) {
 138  4
                                 doForceHttps = true;
 139  4
                                 if (httpsPort.intValue() == 443) {
 140  1
                                         includePort = false;
 141  
                                 }
 142  
                                 else {
 143  3
                                         includePort = true;
 144  
                                 }
 145  
                         }
 146  
 
 147  
                 }
 148  
 
 149  8
                 String loginForm = determineUrlToUseForThisRequest(req, resp, authException);
 150  
 
 151  8
                 if (serverSideRedirect) {
 152  
 
 153  0
                         if (doForceHttps) {
 154  
 
 155  
                                 // before doing server side redirect, we need to do client
 156  
                                 // redirect to https.
 157  
 
 158  0
                                 String servletPath = req.getServletPath();
 159  0
                                 String pathInfo = req.getPathInfo();
 160  0
                                 String query = req.getQueryString();
 161  
 
 162  0
                                 redirectUrl = "https://" + serverName + ((includePort) ? (":" + httpsPort) : "") + contextPath
 163  
                                                 + servletPath + (pathInfo == null ? "" : pathInfo) + (query == null ? "" : "?" + query);
 164  
 
 165  0
                         }
 166  
                         else {
 167  
 
 168  0
                                 if (logger.isDebugEnabled()) {
 169  0
                                         logger.debug("Server side forward to: " + loginForm);
 170  
                                 }
 171  
 
 172  0
                                 RequestDispatcher dispatcher = req.getRequestDispatcher(loginForm);
 173  
 
 174  0
                                 dispatcher.forward(request, response);
 175  
 
 176  0
                                 return;
 177  
 
 178  
                         }
 179  
 
 180  
                 }
 181  
                 else {
 182  
 
 183  8
                         if (doForceHttps) {
 184  
 
 185  4
                                 redirectUrl = "https://" + serverName + ((includePort) ? (":" + httpsPort) : "") + contextPath
 186  
                                                 + loginForm;
 187  
 
 188  
                         }
 189  
                         else {
 190  
 
 191  4
                                 redirectUrl = scheme + "://" + serverName + ((includePort) ? (":" + serverPort) : "") + contextPath
 192  
                                                 + loginForm;
 193  
 
 194  
                         }
 195  
                 }
 196  
 
 197  8
                 if (logger.isDebugEnabled()) {
 198  0
                         logger.debug("Redirecting to: " + redirectUrl);
 199  
                 }
 200  
 
 201  8
                 ((HttpServletResponse) response).sendRedirect(((HttpServletResponse) response).encodeRedirectURL(redirectUrl));
 202  8
         }
 203  
 
 204  
         public boolean getForceHttps() {
 205  2
                 return forceHttps;
 206  
         }
 207  
 
 208  
         public String getLoginFormUrl() {
 209  9
                 return loginFormUrl;
 210  
         }
 211  
 
 212  
         public PortMapper getPortMapper() {
 213  1
                 return portMapper;
 214  
         }
 215  
 
 216  
         public PortResolver getPortResolver() {
 217  1
                 return portResolver;
 218  
         }
 219  
 
 220  
         public boolean isServerSideRedirect() {
 221  0
                 return serverSideRedirect;
 222  
         }
 223  
 
 224  
         /**
 225  
          * Set to true to force login form access to be via https. If this value is
 226  
          * ture (the default is false), and the incoming request for the protected
 227  
          * resource which triggered the interceptor was not already
 228  
          * <code>https</code>, then
 229  
          * 
 230  
          * @param forceHttps
 231  
          */
 232  
         public void setForceHttps(boolean forceHttps) {
 233  6
                 this.forceHttps = forceHttps;
 234  6
         }
 235  
 
 236  
         /**
 237  
          * The URL where the <code>AuthenticationProcessingFilter</code> login
 238  
          * page can be found. Should be relative to the web-app context path, and
 239  
          * include a leading <code>/</code>
 240  
          * 
 241  
          * @param loginFormUrl
 242  
          */
 243  
         public void setLoginFormUrl(String loginFormUrl) {
 244  8
                 this.loginFormUrl = loginFormUrl;
 245  8
         }
 246  
 
 247  
         public void setPortMapper(PortMapper portMapper) {
 248  11
                 this.portMapper = portMapper;
 249  11
         }
 250  
 
 251  
         public void setPortResolver(PortResolver portResolver) {
 252  10
                 this.portResolver = portResolver;
 253  10
         }
 254  
 
 255  
         /**
 256  
          * Tells if we are to do a server side include of the
 257  
          * <code>loginFormUrl</code> instead of a 302 redirect.
 258  
          * 
 259  
          * @param serverSideRedirect
 260  
          */
 261  
         public void setServerSideRedirect(boolean serverSideRedirect) {
 262  0
                 this.serverSideRedirect = serverSideRedirect;
 263  0
         }
 264  
 
 265  
 }