Coverage Report - org.acegisecurity.ui.AbstractProcessingFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractProcessingFilter
23% 
5% 
1.658
 
 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;
 17  
 
 18  
 import org.acegisecurity.AcegiMessageSource;
 19  
 import org.acegisecurity.Authentication;
 20  
 import org.acegisecurity.AuthenticationException;
 21  
 import org.acegisecurity.AuthenticationManager;
 22  
 
 23  
 import org.acegisecurity.context.SecurityContextHolder;
 24  
 
 25  
 import org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent;
 26  
 
 27  
 import org.acegisecurity.ui.rememberme.NullRememberMeServices;
 28  
 import org.acegisecurity.ui.rememberme.RememberMeServices;
 29  
 import org.acegisecurity.ui.savedrequest.SavedRequest;
 30  
 
 31  
 import org.apache.commons.logging.Log;
 32  
 import org.apache.commons.logging.LogFactory;
 33  
 
 34  
 import org.springframework.beans.factory.InitializingBean;
 35  
 
 36  
 import org.springframework.context.ApplicationEventPublisher;
 37  
 import org.springframework.context.ApplicationEventPublisherAware;
 38  
 import org.springframework.context.MessageSource;
 39  
 import org.springframework.context.MessageSourceAware;
 40  
 import org.springframework.context.support.MessageSourceAccessor;
 41  
 
 42  
 import org.springframework.util.Assert;
 43  
 
 44  
 import java.io.IOException;
 45  
 
 46  
 import java.util.Properties;
 47  
 
 48  
 import javax.servlet.Filter;
 49  
 import javax.servlet.FilterChain;
 50  
 import javax.servlet.FilterConfig;
 51  
 import javax.servlet.ServletException;
 52  
 import javax.servlet.ServletRequest;
 53  
 import javax.servlet.ServletResponse;
 54  
 import javax.servlet.http.HttpServletRequest;
 55  
 import javax.servlet.http.HttpServletResponse;
 56  
 
 57  
 /**
 58  
  * Abstract processor of browser-based HTTP-based authentication requests.
 59  
  * <p>
 60  
  * This filter is responsible for processing authentication requests. If
 61  
  * authentication is successful, the resulting {@link Authentication} object
 62  
  * will be placed into the <code>SecurityContext</code>, which is guaranteed
 63  
  * to have already been created by an earlier filter.
 64  
  * </p>
 65  
  * <p>
 66  
  * If authentication fails, the <code>AuthenticationException</code> will be
 67  
  * placed into the <code>HttpSession</code> with the attribute defined by
 68  
  * {@link #ACEGI_SECURITY_LAST_EXCEPTION_KEY}.
 69  
  * </p>
 70  
  * <p>
 71  
  * To use this filter, it is necessary to specify the following properties:
 72  
  * </p>
 73  
  * <ul>
 74  
  * <li><code>defaultTargetUrl</code> indicates the URL that should be used
 75  
  * for redirection if the <code>HttpSession</code> attribute named
 76  
  * {@link #ACEGI_SAVED_REQUEST_KEY} does not indicate the target URL once
 77  
  * authentication is completed successfully. eg: <code>/</code>. The
 78  
  * <code>defaultTargetUrl</code> will be treated as relative to the web-app's
 79  
  * context path, and should include the leading <code>/</code>.
 80  
  * Alternatively, inclusion of a scheme name (eg http:// or https://) as the
 81  
  * prefix will denote a fully-qualified URL and this is also supported.</li>
 82  
  * <li><code>authenticationFailureUrl</code> indicates the URL that should be
 83  
  * used for redirection if the authentication request fails. eg:
 84  
  * <code>/login.jsp?login_error=1</code>.</li>
 85  
  * <li><code>filterProcessesUrl</code> indicates the URL that this filter
 86  
  * will respond to. This parameter varies by subclass.</li>
 87  
  * <li><code>alwaysUseDefaultTargetUrl</code> causes successful
 88  
  * authentication to always redirect to the <code>defaultTargetUrl</code>,
 89  
  * even if the <code>HttpSession</code> attribute named {@link
 90  
  * #ACEGI_SAVED_REQUEST_KEY} defines the intended target URL.</li>
 91  
  * </ul>
 92  
  * <p>
 93  
  * To configure this filter to redirect to specific pages as the result of
 94  
  * specific {@link AuthenticationException}s you can do the following.
 95  
  * Configure the <code>exceptionMappings</code> property in your application
 96  
  * xml. This property is a java.util.Properties object that maps a
 97  
  * fully-qualified exception class name to a redirection url target. For
 98  
  * example:
 99  
  * 
 100  
  * <pre>
 101  
  *  &lt;property name=&quot;exceptionMappings&quot;&gt;
 102  
  *    &lt;props&gt;
 103  
  *      &lt;prop&gt; key=&quot;org.acegisecurity.BadCredentialsException&quot;&gt;/bad_credentials.jsp&lt;/prop&gt;
 104  
  *    &lt;/props&gt;
 105  
  *  &lt;/property&gt;
 106  
  * </pre>
 107  
  * 
 108  
  * The example above would redirect all
 109  
  * {@link org.acegisecurity.BadCredentialsException}s thrown, to a page in the
 110  
  * web-application called /bad_credentials.jsp.
 111  
  * </p>
 112  
  * <p>
 113  
  * Any {@link AuthenticationException} thrown that cannot be matched in the
 114  
  * <code>exceptionMappings</code> will be redirected to the
 115  
  * <code>authenticationFailureUrl</code>
 116  
  * </p>
 117  
  * <p>
 118  
  * If authentication is successful, an {@link
 119  
  * org.acegisecurity.event.authentication.InteractiveAuthenticationSuccessEvent}
 120  
  * will be published to the application context. No events will be published if
 121  
  * authentication was unsuccessful, because this would generally be recorded via
 122  
  * an <code>AuthenticationManager</code>-specific application event.
 123  
  * </p>
 124  
  * 
 125  
  * @author Ben Alex
 126  
  * @version $Id: AbstractProcessingFilter.java 1909 2007-06-19 04:08:19Z
 127  
  * vishalpuri $
 128  
  */
 129  13
 public abstract class AbstractProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware,
 130  
                 MessageSourceAware {
 131  
         // ~ Static fields/initializers
 132  
         // =====================================================================================
 133  
 
 134  
         public static final String ACEGI_SAVED_REQUEST_KEY = "ACEGI_SAVED_REQUEST_KEY";
 135  
 
 136  
         public static final String ACEGI_SECURITY_LAST_EXCEPTION_KEY = "ACEGI_SECURITY_LAST_EXCEPTION";
 137  
 
 138  
         // ~ Instance fields
 139  
         // ================================================================================================
 140  
 
 141  
         protected ApplicationEventPublisher eventPublisher;
 142  
 
 143  13
         protected AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl();
 144  
 
 145  
         private AuthenticationManager authenticationManager;
 146  
 
 147  13
         protected final Log logger = LogFactory.getLog(this.getClass());
 148  
 
 149  13
         protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
 150  
 
 151  13
         private Properties exceptionMappings = new Properties();
 152  
 
 153  13
         private RememberMeServices rememberMeServices = new NullRememberMeServices();
 154  
 
 155  
         /** Where to redirect the browser to if authentication fails */
 156  
         private String authenticationFailureUrl;
 157  
 
 158  
         /**
 159  
          * Where to redirect the browser to if authentication is successful but
 160  
          * ACEGI_SAVED_REQUEST_KEY is <code>null</code>
 161  
          */
 162  
         private String defaultTargetUrl;
 163  
 
 164  
         /**
 165  
          * The URL destination that this filter intercepts and processes (usually
 166  
          * something like <code>/j_acegi_security_check</code>)
 167  
          */
 168  13
         private String filterProcessesUrl = getDefaultFilterProcessesUrl();
 169  
 
 170  
         /**
 171  
          * If <code>true</code>, will always redirect to the value of
 172  
          * {@link #getDefaultTargetUrl} upon successful authentication, irrespective
 173  
          * of the page that caused the authentication request (defaults to
 174  
          * <code>false</code>).
 175  
          */
 176  13
         private boolean alwaysUseDefaultTargetUrl = false;
 177  
 
 178  
         /**
 179  
          * Indicates if the filter chain should be continued prior to delegation to
 180  
          * {@link #successfulAuthentication(HttpServletRequest, HttpServletResponse,
 181  
          * Authentication)}, which may be useful in certain environment (eg
 182  
          * Tapestry). Defaults to <code>false</code>.
 183  
          */
 184  13
         private boolean continueChainBeforeSuccessfulAuthentication = false;
 185  
 
 186  
         /**
 187  
          * Specifies the buffer size to use in the event of a directory. A buffer
 188  
          * size is used to ensure the response is not written back to the client
 189  
          * immediately. This provides a way for the <code>HttpSession</code> to be
 190  
          * updated before the browser redirect will be sent. Defaults to an 8 Kb
 191  
          * buffer.
 192  
          */
 193  13
         private int bufferSize = 8 * 1024;
 194  
 
 195  
         /**
 196  
          * If true, causes any redirection URLs to be calculated minus the protocol
 197  
          * and context path (defaults to false).
 198  
          */
 199  13
         private boolean useRelativeContext = false;
 200  
 
 201  
         // ~ Methods
 202  
         // ========================================================================================================
 203  
 
 204  
         public void afterPropertiesSet() throws Exception {
 205  0
                 Assert.hasLength(filterProcessesUrl, "filterProcessesUrl must be specified");
 206  0
                 Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified");
 207  0
                 Assert.hasLength(authenticationFailureUrl, "authenticationFailureUrl must be specified");
 208  0
                 Assert.notNull(authenticationManager, "authenticationManager must be specified");
 209  0
                 Assert.notNull(this.rememberMeServices);
 210  0
         }
 211  
 
 212  
         /**
 213  
          * Performs actual authentication.
 214  
          * 
 215  
          * @param request from which to extract parameters and perform the
 216  
          * authentication
 217  
          * 
 218  
          * @return the authenticated user
 219  
          * 
 220  
          * @throws AuthenticationException if authentication fails
 221  
          */
 222  
         public abstract Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException;
 223  
 
 224  
         /**
 225  
          * Does nothing. We use IoC container lifecycle services instead.
 226  
          */
 227  
         public void destroy() {
 228  0
         }
 229  
 
 230  
         public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
 231  
                         ServletException {
 232  0
                 if (!(request instanceof HttpServletRequest)) {
 233  0
                         throw new ServletException("Can only process HttpServletRequest");
 234  
                 }
 235  
 
 236  0
                 if (!(response instanceof HttpServletResponse)) {
 237  0
                         throw new ServletException("Can only process HttpServletResponse");
 238  
                 }
 239  
 
 240  0
                 HttpServletRequest httpRequest = (HttpServletRequest) request;
 241  0
                 HttpServletResponse httpResponse = (HttpServletResponse) response;
 242  
 
 243  0
                 if (requiresAuthentication(httpRequest, httpResponse)) {
 244  0
                         if (logger.isDebugEnabled()) {
 245  0
                                 logger.debug("Request is to process authentication");
 246  
                         }
 247  
 
 248  
                         Authentication authResult;
 249  
 
 250  
                         try {
 251  0
                                 onPreAuthentication(httpRequest, httpResponse);
 252  0
                                 authResult = attemptAuthentication(httpRequest);
 253  
                         }
 254  0
                         catch (AuthenticationException failed) {
 255  
                                 // Authentication failed
 256  0
                                 unsuccessfulAuthentication(httpRequest, httpResponse, failed);
 257  
 
 258  0
                                 return;
 259  0
                         }
 260  
 
 261  
                         // Authentication success
 262  0
                         if (continueChainBeforeSuccessfulAuthentication) {
 263  0
                                 chain.doFilter(request, response);
 264  
                         }
 265  
 
 266  0
                         successfulAuthentication(httpRequest, httpResponse, authResult);
 267  
 
 268  0
                         return;
 269  
                 }
 270  
 
 271  0
                 chain.doFilter(request, response);
 272  0
         }
 273  
 
 274  
         public String getAuthenticationFailureUrl() {
 275  1
                 return authenticationFailureUrl;
 276  
         }
 277  
 
 278  
         public AuthenticationManager getAuthenticationManager() {
 279  9
                 return authenticationManager;
 280  
         }
 281  
 
 282  
         /**
 283  
          * Specifies the default <code>filterProcessesUrl</code> for the
 284  
          * implementation.
 285  
          * 
 286  
          * @return the default <code>filterProcessesUrl</code>
 287  
          */
 288  
         public abstract String getDefaultFilterProcessesUrl();
 289  
 
 290  
         /**
 291  
          * Supplies the default target Url that will be used if no saved request is
 292  
          * found or the <tt>alwaysUseDefaultTargetUrl</tt> propert is set to true.
 293  
          * Override this method of you want to provide a customized default Url (for
 294  
          * example if you want different Urls depending on the authorities of the
 295  
          * user who has just logged in).
 296  
          * 
 297  
          * @return the defaultTargetUrl property
 298  
          */
 299  
         public String getDefaultTargetUrl() {
 300  6
                 return defaultTargetUrl;
 301  
         }
 302  
 
 303  
         public Properties getExceptionMappings() {
 304  0
                 return new Properties(exceptionMappings);
 305  
         }
 306  
 
 307  
         public String getFilterProcessesUrl() {
 308  5
                 return filterProcessesUrl;
 309  
         }
 310  
 
 311  
         public RememberMeServices getRememberMeServices() {
 312  0
                 return rememberMeServices;
 313  
         }
 314  
 
 315  
         /**
 316  
          * Does nothing. We use IoC container lifecycle services instead.
 317  
          * 
 318  
          * @param arg0 ignored
 319  
          * 
 320  
          * @throws ServletException ignored
 321  
          */
 322  
         public void init(FilterConfig arg0) throws ServletException {
 323  0
         }
 324  
 
 325  
         public boolean isAlwaysUseDefaultTargetUrl() {
 326  1
                 return alwaysUseDefaultTargetUrl;
 327  
         }
 328  
 
 329  
         public boolean isContinueChainBeforeSuccessfulAuthentication() {
 330  1
                 return continueChainBeforeSuccessfulAuthentication;
 331  
         }
 332  
 
 333  
         public static String obtainFullRequestUrl(HttpServletRequest request) {
 334  3
                 SavedRequest savedRequest = (SavedRequest) request.getSession().getAttribute(
 335  
                                 AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY);
 336  
 
 337  3
                 return (savedRequest == null) ? null : savedRequest.getFullRequestUrl();
 338  
         }
 339  
 
 340  
         protected void onPreAuthentication(HttpServletRequest request, HttpServletResponse response)
 341  
                         throws AuthenticationException, IOException {
 342  0
         }
 343  
 
 344  
         protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
 345  
                         Authentication authResult) throws IOException {
 346  0
         }
 347  
 
 348  
         protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
 349  
                         AuthenticationException failed) throws IOException {
 350  0
         }
 351  
 
 352  
         /**
 353  
          * <p>
 354  
          * Indicates whether this filter should attempt to process a login request
 355  
          * for the current invocation.
 356  
          * </p>
 357  
          * <p>
 358  
          * It strips any parameters from the "path" section of the request URL (such
 359  
          * as the jsessionid parameter in
 360  
          * <em>http://host/myapp/index.html;jsessionid=blah</em>) before matching
 361  
          * against the <code>filterProcessesUrl</code> property.
 362  
          * </p>
 363  
          * <p>
 364  
          * Subclasses may override for special requirements, such as Tapestry
 365  
          * integration.
 366  
          * </p>
 367  
          * 
 368  
          * @param request as received from the filter chain
 369  
          * @param response as received from the filter chain
 370  
          * 
 371  
          * @return <code>true</code> if the filter should attempt authentication,
 372  
          * <code>false</code> otherwise
 373  
          */
 374  
         protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
 375  0
                 String uri = request.getRequestURI();
 376  0
                 int pathParamIndex = uri.indexOf(';');
 377  
 
 378  0
                 if (pathParamIndex > 0) {
 379  
                         // strip everything after the first semi-colon
 380  0
                         uri = uri.substring(0, pathParamIndex);
 381  
                 }
 382  
 
 383  0
                 if ("".equals(request.getContextPath())) {
 384  0
                         return uri.endsWith(filterProcessesUrl);
 385  
                 }
 386  
 
 387  0
                 return uri.endsWith(request.getContextPath() + filterProcessesUrl);
 388  
         }
 389  
 
 390  
         protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
 391  
                         throws IOException {
 392  
                 String finalUrl;
 393  0
                 if (!url.startsWith("http://") && !url.startsWith("https://")) {
 394  0
                         if (useRelativeContext) {
 395  0
                                 finalUrl = url;
 396  
                         }
 397  
                         else {
 398  0
                                 finalUrl = request.getContextPath() + url;
 399  
                         }
 400  
                 }
 401  0
                 else if (useRelativeContext) {
 402  
                         // Calculate the relative URL from the fully qualifed URL, minus the
 403  
                         // protocol and base context.
 404  0
                         int len = request.getContextPath().length();
 405  0
                         int index = url.indexOf(request.getContextPath()) + len;
 406  0
                         finalUrl = url.substring(index);
 407  0
                         if (finalUrl.length() > 1 && finalUrl.charAt(0) == '/') {
 408  0
                                 finalUrl = finalUrl.substring(1);
 409  
                         }
 410  0
                 }
 411  
                 else {
 412  0
                         finalUrl = url;
 413  
                 }
 414  
 
 415  0
                 Assert.isTrue(!response.isCommitted(),
 416  
                                 "Response already committed; the authentication mechanism must be able to modify buffer size");
 417  0
                 response.setBufferSize(bufferSize);
 418  0
                 response.sendRedirect(response.encodeRedirectURL(finalUrl));
 419  0
         }
 420  
 
 421  
         public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
 422  1
                 this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl;
 423  1
         }
 424  
 
 425  
         public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
 426  0
                 this.eventPublisher = eventPublisher;
 427  0
         }
 428  
 
 429  
         public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
 430  0
                 Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
 431  0
                 this.authenticationDetailsSource = authenticationDetailsSource;
 432  0
         }
 433  
 
 434  
         public void setAuthenticationFailureUrl(String authenticationFailureUrl) {
 435  1
                 this.authenticationFailureUrl = authenticationFailureUrl;
 436  1
         }
 437  
 
 438  
         public void setAuthenticationManager(AuthenticationManager authenticationManager) {
 439  10
                 this.authenticationManager = authenticationManager;
 440  10
         }
 441  
 
 442  
         public void setContinueChainBeforeSuccessfulAuthentication(boolean continueChainBeforeSuccessfulAuthentication) {
 443  1
                 this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication;
 444  1
         }
 445  
 
 446  
         public void setDefaultTargetUrl(String defaultTargetUrl) {
 447  2
                 Assert.isTrue(defaultTargetUrl.startsWith("/") | defaultTargetUrl.startsWith("http"),
 448  
                                 "defaultTarget must start with '/' or with 'http(s)'");
 449  2
                 this.defaultTargetUrl = defaultTargetUrl;
 450  2
         }
 451  
 
 452  
         public void setExceptionMappings(Properties exceptionMappings) {
 453  0
                 this.exceptionMappings = exceptionMappings;
 454  0
         }
 455  
 
 456  
         public void setFilterProcessesUrl(String filterProcessesUrl) {
 457  1
                 this.filterProcessesUrl = filterProcessesUrl;
 458  1
         }
 459  
 
 460  
         public void setMessageSource(MessageSource messageSource) {
 461  0
                 this.messages = new MessageSourceAccessor(messageSource);
 462  0
         }
 463  
 
 464  
         public void setRememberMeServices(RememberMeServices rememberMeServices) {
 465  0
                 this.rememberMeServices = rememberMeServices;
 466  0
         }
 467  
 
 468  
         protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
 469  
                         Authentication authResult) throws IOException {
 470  0
                 if (logger.isDebugEnabled()) {
 471  0
                         logger.debug("Authentication success: " + authResult.toString());
 472  
                 }
 473  
 
 474  0
                 SecurityContextHolder.getContext().setAuthentication(authResult);
 475  
 
 476  0
                 if (logger.isDebugEnabled()) {
 477  0
                         logger.debug("Updated SecurityContextHolder to contain the following Authentication: '" + authResult + "'");
 478  
                 }
 479  
 
 480  0
                 String targetUrl = determineTargetUrl(request);
 481  
 
 482  0
                 if (logger.isDebugEnabled()) {
 483  0
                         logger.debug("Redirecting to target URL from HTTP Session (or default): " + targetUrl);
 484  
                 }
 485  
 
 486  0
                 onSuccessfulAuthentication(request, response, authResult);
 487  
 
 488  0
                 rememberMeServices.loginSuccess(request, response, authResult);
 489  
 
 490  
                 // Fire event
 491  0
                 if (this.eventPublisher != null) {
 492  0
                         eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
 493  
                 }
 494  
 
 495  0
                 sendRedirect(request, response, targetUrl);
 496  0
         }
 497  
 
 498  
         protected String determineTargetUrl(HttpServletRequest request) {
 499  
                 // Don't attempt to obtain the url from the saved request if
 500  
                 // alwaysUsedefaultTargetUrl is set
 501  0
                 String targetUrl = alwaysUseDefaultTargetUrl ? null : obtainFullRequestUrl(request);
 502  
 
 503  0
                 if (targetUrl == null) {
 504  0
                         targetUrl = getDefaultTargetUrl();
 505  
                 }
 506  
 
 507  0
                 return targetUrl;
 508  
         }
 509  
 
 510  
         protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
 511  
                         AuthenticationException failed) throws IOException {
 512  0
                 SecurityContextHolder.getContext().setAuthentication(null);
 513  
 
 514  0
                 if (logger.isDebugEnabled()) {
 515  0
                         logger.debug("Updated SecurityContextHolder to contain null Authentication");
 516  
                 }
 517  
 
 518  0
                 String failureUrl = determineFailureUrl(request, failed);
 519  
 
 520  0
                 if (logger.isDebugEnabled()) {
 521  0
                         logger.debug("Authentication request failed: " + failed.toString());
 522  
                 }
 523  
 
 524  
                 try {
 525  0
                         request.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed);
 526  
                 }
 527  0
                 catch (Exception ignored) {
 528  0
                 }
 529  
 
 530  0
                 onUnsuccessfulAuthentication(request, response, failed);
 531  
 
 532  0
                 rememberMeServices.loginFail(request, response);
 533  
 
 534  0
                 sendRedirect(request, response, failureUrl);
 535  0
         }
 536  
 
 537  
     protected String determineFailureUrl(HttpServletRequest request, AuthenticationException failed) {
 538  0
         return exceptionMappings.getProperty(failed.getClass().getName(), authenticationFailureUrl);
 539  
     }
 540  
 
 541  
     public AuthenticationDetailsSource getAuthenticationDetailsSource() {
 542  
                 // Required due to SEC-310
 543  0
                 return authenticationDetailsSource;
 544  
         }
 545  
 
 546  
         public void setBufferSize(int bufferSize) {
 547  0
                 this.bufferSize = bufferSize;
 548  0
         }
 549  
 
 550  
         public void setUseRelativeContext(boolean useRelativeContext) {
 551  0
                 this.useRelativeContext = useRelativeContext;
 552  0
         }
 553  
 
 554  
 }