Coverage Report - org.acegisecurity.captcha.CaptchaEntryPoint
 
Classes in this File Line Coverage Branch Coverage Complexity
CaptchaEntryPoint
86% 
100% 
1.567
 
 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.captcha;
 17  
 
 18  
 import org.acegisecurity.securechannel.ChannelEntryPoint;
 19  
 
 20  
 import org.acegisecurity.util.PortMapper;
 21  
 import org.acegisecurity.util.PortMapperImpl;
 22  
 import org.acegisecurity.util.PortResolver;
 23  
 import org.acegisecurity.util.PortResolverImpl;
 24  
 
 25  
 import org.apache.commons.logging.Log;
 26  
 import org.apache.commons.logging.LogFactory;
 27  
 
 28  
 import org.springframework.beans.factory.InitializingBean;
 29  
 
 30  
 import org.springframework.util.Assert;
 31  
 
 32  
 import java.io.IOException;
 33  
 import java.io.UnsupportedEncodingException;
 34  
 
 35  
 import java.net.URLEncoder;
 36  
 
 37  
 import java.util.Enumeration;
 38  
 
 39  
 import javax.servlet.ServletException;
 40  
 import javax.servlet.ServletRequest;
 41  
 import javax.servlet.ServletResponse;
 42  
 import javax.servlet.http.HttpServletRequest;
 43  
 import javax.servlet.http.HttpServletResponse;
 44  
 
 45  
 
 46  
 /**
 47  
  * The captcha entry point : redirect to the captcha test page.
 48  
  * <p>
 49  
  * This entry point can force the use of SSL : see {@link #getForceHttps()}
 50  
  * </p>
 51  
  * <p>
 52  
  * This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}<br />
 53  
  * / Original request can be added to the redirect path using a custom translation : see
 54  
  * {@link #setIncludeOriginalRequest(boolean)}<br />
 55  
  * The original request is translated using URLEncoding and the following translation mapping in the redirect url :
 56  
  *  <ul>
 57  
  *      <li>original url => {@link #getOriginalRequestUrlParameterName()}</li>
 58  
  *      <li>If {@link #isIncludeOriginalParameters()}</li>
 59  
  *      <li>original method => {@link #getOriginalRequestMethodParameterName()}</li>
 60  
  *      <li>original parameters => {@link #getOriginalRequestParametersParameterName()}</li>
 61  
  *      <li>The original parameters string is contructed using :
 62  
  *      <ul>
 63  
  *          <li>a parameter separator {@link #getOriginalRequestParametersSeparator()}</li>
 64  
  *          <li>a parameter name value pair separator for each parameter {@link
 65  
  *          #getOriginalRequestParametersNameValueSeparator()}</li>
 66  
  *      </ul>
 67  
  *      </li>
 68  
  *  </ul>
 69  
  *  <br><br>
 70  
  * Default values :
 71  
  * <pre>
 72  
  * forceHttps = false
 73  
  * includesOriginalRequest = true
 74  
  * includesOriginalParameters = false
 75  
  * isOutsideWebApp = false
 76  
  * originalRequestUrlParameterName = original_requestUrl
 77  
  * originalRequestParametersParameterName = original_request_parameters
 78  
  * originalRequestParametersNameValueSeparator = __
 79  
  * originalRequestParametersSeparator = ;;
 80  
  * originalRequestMethodParameterName = original_request_method
 81  
  * urlEncodingCharset = UTF-8
 82  
  * </pre>
 83  
  * </p>
 84  
  *
 85  
  * @author marc antoine Garrigue
 86  
  * @version $Id: CaptchaEntryPoint.java 1784 2007-02-24 21:00:24Z luke_t $
 87  
  */
 88  15
 public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
 89  
     //~ Static fields/initializers =====================================================================================
 90  
 
 91  2
     private static final Log logger = LogFactory.getLog(CaptchaEntryPoint.class);
 92  
 
 93  
     //~ Instance fields ================================================================================================
 94  
 
 95  
     // ~ Instance fields
 96  
     // ========================================================
 97  15
     private PortMapper portMapper = new PortMapperImpl();
 98  15
     private PortResolver portResolver = new PortResolverImpl();
 99  
     private String captchaFormUrl;
 100  15
     private String originalRequestMethodParameterName = "original_request_method";
 101  15
     private String originalRequestParametersNameValueSeparator = "__";
 102  15
     private String originalRequestParametersParameterName = "original_request_parameters";
 103  15
     private String originalRequestParametersSeparator = ";;";
 104  15
     private String originalRequestUrlParameterName = "original_requestUrl";
 105  15
     private String urlEncodingCharset = "UTF-8";
 106  15
     private boolean forceHttps = false;
 107  15
     private boolean includeOriginalParameters = false;
 108  15
     private boolean includeOriginalRequest = true;
 109  15
     private boolean isOutsideWebApp = false;
 110  
 
 111  
     //~ Methods ========================================================================================================
 112  
 
 113  
     public void afterPropertiesSet() throws Exception {
 114  14
         Assert.hasLength(captchaFormUrl, "captchaFormUrl must be specified");
 115  13
         Assert.hasLength(originalRequestMethodParameterName, "originalRequestMethodParameterName must be specified");
 116  13
         Assert.hasLength(originalRequestParametersNameValueSeparator,
 117  
             "originalRequestParametersNameValueSeparator must be specified");
 118  13
         Assert.hasLength(originalRequestParametersParameterName,
 119  
             "originalRequestParametersParameterName must be specified");
 120  13
         Assert.hasLength(originalRequestParametersSeparator, "originalRequestParametersSeparator must be specified");
 121  13
         Assert.hasLength(originalRequestUrlParameterName, "originalRequestUrlParameterName must be specified");
 122  13
         Assert.hasLength(urlEncodingCharset, "urlEncodingCharset must be specified");
 123  13
         Assert.notNull(portMapper, "portMapper must be specified");
 124  12
         Assert.notNull(portResolver, "portResolver must be specified");
 125  11
         URLEncoder.encode("   fzaef é& à ", urlEncodingCharset);
 126  11
     }
 127  
 
 128  
     private void buildInternalRedirect(StringBuffer redirectUrl, HttpServletRequest req) {
 129  
         // construct it
 130  15
         StringBuffer simpleRedirect = new StringBuffer();
 131  
 
 132  15
         String scheme = req.getScheme();
 133  15
         String serverName = req.getServerName();
 134  15
         int serverPort = portResolver.getServerPort(req);
 135  15
         String contextPath = req.getContextPath();
 136  15
         boolean includePort = true;
 137  
 
 138  15
         if ("http".equals(scheme.toLowerCase()) && (serverPort == 80)) {
 139  2
             includePort = false;
 140  
         }
 141  
 
 142  15
         if ("https".equals(scheme.toLowerCase()) && (serverPort == 443)) {
 143  1
             includePort = false;
 144  
         }
 145  
 
 146  15
         simpleRedirect.append(scheme);
 147  15
         simpleRedirect.append("://");
 148  15
         simpleRedirect.append(serverName);
 149  
 
 150  15
         if (includePort) {
 151  12
             simpleRedirect.append(":");
 152  12
             simpleRedirect.append(serverPort);
 153  
         }
 154  
 
 155  15
         simpleRedirect.append(contextPath);
 156  15
         simpleRedirect.append(captchaFormUrl);
 157  
 
 158  15
         if (forceHttps && req.getScheme().equals("http")) {
 159  6
             Integer httpPort = new Integer(portResolver.getServerPort(req));
 160  6
             Integer httpsPort = (Integer) portMapper.lookupHttpsPort(httpPort);
 161  
 
 162  6
             if (httpsPort != null) {
 163  5
                 if (httpsPort.intValue() == 443) {
 164  1
                     includePort = false;
 165  
                 } else {
 166  4
                     includePort = true;
 167  
                 }
 168  
 
 169  5
                 redirectUrl.append("https://");
 170  5
                 redirectUrl.append(serverName);
 171  
 
 172  5
                 if (includePort) {
 173  4
                     redirectUrl.append(":");
 174  4
                     redirectUrl.append(httpsPort);
 175  
                 }
 176  
 
 177  5
                 redirectUrl.append(contextPath);
 178  5
                 redirectUrl.append(captchaFormUrl);
 179  
             } else {
 180  1
                 redirectUrl.append(simpleRedirect);
 181  
             }
 182  6
         } else {
 183  9
             redirectUrl.append(simpleRedirect);
 184  
         }
 185  15
     }
 186  
 
 187  
     public void commence(ServletRequest request, ServletResponse response)
 188  
         throws IOException, ServletException {
 189  20
         StringBuffer redirectUrl = new StringBuffer();
 190  20
         HttpServletRequest req = (HttpServletRequest) request;
 191  
 
 192  20
         if (isOutsideWebApp) {
 193  5
             redirectUrl = redirectUrl.append(captchaFormUrl);
 194  
         } else {
 195  15
             buildInternalRedirect(redirectUrl, req);
 196  
         }
 197  
 
 198  20
         if (includeOriginalRequest) {
 199  11
             includeOriginalRequest(redirectUrl, req);
 200  
         }
 201  
 
 202  
         // add post parameter? DONE!
 203  20
         if (logger.isDebugEnabled()) {
 204  0
             logger.debug("Redirecting to: " + redirectUrl);
 205  
         }
 206  
 
 207  20
         ((HttpServletResponse) response).sendRedirect(redirectUrl.toString());
 208  20
     }
 209  
 
 210  
     /**
 211  
      * DOCUMENT ME!
 212  
      *
 213  
      * @return the captcha test page to redirect to.
 214  
      */
 215  
     public String getCaptchaFormUrl() {
 216  1
         return captchaFormUrl;
 217  
     }
 218  
 
 219  
     public boolean getForceHttps() {
 220  2
         return forceHttps;
 221  
     }
 222  
 
 223  
     public String getOriginalRequestMethodParameterName() {
 224  0
         return originalRequestMethodParameterName;
 225  
     }
 226  
 
 227  
     public String getOriginalRequestParametersNameValueSeparator() {
 228  0
         return originalRequestParametersNameValueSeparator;
 229  
     }
 230  
 
 231  
     public String getOriginalRequestParametersParameterName() {
 232  0
         return originalRequestParametersParameterName;
 233  
     }
 234  
 
 235  
     public String getOriginalRequestParametersSeparator() {
 236  0
         return originalRequestParametersSeparator;
 237  
     }
 238  
 
 239  
     public String getOriginalRequestUrlParameterName() {
 240  2
         return originalRequestUrlParameterName;
 241  
     }
 242  
 
 243  
     public PortMapper getPortMapper() {
 244  1
         return portMapper;
 245  
     }
 246  
 
 247  
     public PortResolver getPortResolver() {
 248  1
         return portResolver;
 249  
     }
 250  
 
 251  
     public String getUrlEncodingCharset() {
 252  0
         return urlEncodingCharset;
 253  
     }
 254  
 
 255  
     private void includeOriginalRequest(StringBuffer redirectUrl, HttpServletRequest req) {
 256  
         // add original request to the url
 257  11
         if (redirectUrl.indexOf("?") >= 0) {
 258  4
             redirectUrl.append("&");
 259  
         } else {
 260  7
             redirectUrl.append("?");
 261  
         }
 262  
 
 263  11
         redirectUrl.append(originalRequestUrlParameterName);
 264  11
         redirectUrl.append("=");
 265  
 
 266  
         try {
 267  11
             redirectUrl.append(URLEncoder.encode(req.getRequestURL().toString(), urlEncodingCharset));
 268  0
         } catch (UnsupportedEncodingException e) {
 269  0
             logger.warn(e);
 270  11
         }
 271  
 
 272  
         //append method
 273  11
         redirectUrl.append("&");
 274  11
         redirectUrl.append(originalRequestMethodParameterName);
 275  11
         redirectUrl.append("=");
 276  11
         redirectUrl.append(req.getMethod());
 277  
 
 278  11
         if (includeOriginalParameters) {
 279  
             // append query params
 280  6
             redirectUrl.append("&");
 281  6
             redirectUrl.append(originalRequestParametersParameterName);
 282  6
             redirectUrl.append("=");
 283  
 
 284  6
             StringBuffer qp = new StringBuffer();
 285  6
             Enumeration parameters = req.getParameterNames();
 286  
 
 287  6
             if ((parameters != null) && parameters.hasMoreElements()) {
 288  
                 //qp.append("?");
 289  18
                 while (parameters.hasMoreElements()) {
 290  12
                     String name = parameters.nextElement().toString();
 291  12
                     String value = req.getParameter(name);
 292  12
                     qp.append(name);
 293  12
                     qp.append(originalRequestParametersNameValueSeparator);
 294  12
                     qp.append(value);
 295  
 
 296  12
                     if (parameters.hasMoreElements()) {
 297  6
                         qp.append(originalRequestParametersSeparator);
 298  
                     }
 299  12
                 }
 300  
             }
 301  
 
 302  
             try {
 303  6
                 redirectUrl.append(URLEncoder.encode(qp.toString(), urlEncodingCharset));
 304  0
             } catch (Exception e) {
 305  0
                 logger.warn(e);
 306  6
             }
 307  
         }
 308  11
     }
 309  
 
 310  
     public boolean isIncludeOriginalParameters() {
 311  0
         return includeOriginalParameters;
 312  
     }
 313  
 
 314  
     public boolean isIncludeOriginalRequest() {
 315  2
         return includeOriginalRequest;
 316  
     }
 317  
 
 318  
     public boolean isOutsideWebApp() {
 319  2
         return isOutsideWebApp;
 320  
     }
 321  
 
 322  
     /**
 323  
      * The URL where the <code>CaptchaProcessingFilter</code> login page can be found. Should be relative to
 324  
      * the web-app context path, and include a leading <code>/</code>
 325  
      *
 326  
      * @param captchaFormUrl
 327  
      */
 328  
     public void setCaptchaFormUrl(String captchaFormUrl) {
 329  14
         this.captchaFormUrl = captchaFormUrl;
 330  14
     }
 331  
 
 332  
     // ~ Methods
 333  
     // ================================================================
 334  
     /**
 335  
      * Set to true to force captcha form access to be via https. If this value is ture (the default is false),
 336  
      * and the incoming request for the protected resource which triggered the interceptor was not already
 337  
      * <code>https</code>, then
 338  
      *
 339  
      * @param forceHttps
 340  
      */
 341  
     public void setForceHttps(boolean forceHttps) {
 342  8
         this.forceHttps = forceHttps;
 343  8
     }
 344  
 
 345  
     public void setIncludeOriginalParameters(boolean includeOriginalParameters) {
 346  2
         this.includeOriginalParameters = includeOriginalParameters;
 347  2
     }
 348  
 
 349  
     /**
 350  
      * If set to true, the original request url will be appended to the redirect url using the {@link
 351  
      * #getOriginalRequestUrlParameterName()}.
 352  
      *
 353  
      * @param includeOriginalRequest
 354  
      */
 355  
     public void setIncludeOriginalRequest(boolean includeOriginalRequest) {
 356  9
         this.includeOriginalRequest = includeOriginalRequest;
 357  9
     }
 358  
 
 359  
     public void setOriginalRequestMethodParameterName(String originalRequestMethodParameterName) {
 360  0
         this.originalRequestMethodParameterName = originalRequestMethodParameterName;
 361  0
     }
 362  
 
 363  
     public void setOriginalRequestParametersNameValueSeparator(String originalRequestParametersNameValueSeparator) {
 364  0
         this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator;
 365  0
     }
 366  
 
 367  
     public void setOriginalRequestParametersParameterName(String originalRequestParametersParameterName) {
 368  0
         this.originalRequestParametersParameterName = originalRequestParametersParameterName;
 369  0
     }
 370  
 
 371  
     public void setOriginalRequestParametersSeparator(String originalRequestParametersSeparator) {
 372  0
         this.originalRequestParametersSeparator = originalRequestParametersSeparator;
 373  0
     }
 374  
 
 375  
     public void setOriginalRequestUrlParameterName(String originalRequestUrlParameterName) {
 376  1
         this.originalRequestUrlParameterName = originalRequestUrlParameterName;
 377  1
     }
 378  
 
 379  
     /**
 380  
      * if set to true, the {@link #commence(ServletRequest, ServletResponse)} method uses the {@link
 381  
      * #getCaptchaFormUrl()} as a complete URL, else it as a 'inside WebApp' path.
 382  
      *
 383  
      * @param isOutsideWebApp
 384  
      */
 385  
     public void setOutsideWebApp(boolean isOutsideWebApp) {
 386  2
         this.isOutsideWebApp = isOutsideWebApp;
 387  2
     }
 388  
 
 389  
     public void setPortMapper(PortMapper portMapper) {
 390  13
         this.portMapper = portMapper;
 391  13
     }
 392  
 
 393  
     public void setPortResolver(PortResolver portResolver) {
 394  12
         this.portResolver = portResolver;
 395  12
     }
 396  
 
 397  
     public void setUrlEncodingCharset(String urlEncodingCharset) {
 398  0
         this.urlEncodingCharset = urlEncodingCharset;
 399  0
     }
 400  
 }