View Javadoc

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.springframework.security.ui;
17  
18  import org.springframework.security.AccessDeniedException;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  import java.io.IOException;
24  
25  import javax.servlet.RequestDispatcher;
26  import javax.servlet.ServletException;
27  import javax.servlet.ServletRequest;
28  import javax.servlet.ServletResponse;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  
33  /**
34   * Base implementation of {@link AccessDeniedHandler}.<p>This implementation sends a 403 (SC_FORBIDDEN) HTTP error
35   * code. In addition, if a {@link #errorPage} is defined, the implementation will perform a request dispatcher
36   * "forward" to the specified error page view. Being a "forward", the <code>SecurityContextHolder</code> will remain
37   * populated. This is of benefit if the view (or a tag library or macro) wishes to access the
38   * <code>SecurityContextHolder</code>. The request scope will also be populated with the exception itself, available
39   * from the key {@link #SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY}.</p>
40   *
41   * @author Ben Alex
42   * @version $Id: AccessDeniedHandlerImpl.java 3038 2008-05-07 13:49:20Z luke_t $
43   */
44  public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
45      //~ Static fields/initializers =====================================================================================
46  
47      public static final String SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY = "SPRING_SECURITY_403_EXCEPTION";
48      protected static final Log logger = LogFactory.getLog(AccessDeniedHandlerImpl.class);
49  
50      //~ Instance fields ================================================================================================
51  
52      private String errorPage;
53  
54      //~ Methods ========================================================================================================
55  
56      public void handle(ServletRequest request, ServletResponse response, AccessDeniedException accessDeniedException)
57              throws IOException, ServletException {
58          if (errorPage != null) {
59              // Put exception into request scope (perhaps of use to a view)
60              ((HttpServletRequest) request).setAttribute(SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY,
61                  accessDeniedException);
62  
63              // Perform RequestDispatcher "forward"
64              RequestDispatcher rd = request.getRequestDispatcher(errorPage);
65              rd.forward(request, response);
66          }
67  
68          if (!response.isCommitted()) {
69              // Send 403 (we do this after response has been written)
70              ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
71          }
72      }
73  
74      /**
75       * The error page to use. Must begin with a "/" and is interpreted relative to the current context root.
76       *
77       * @param errorPage the dispatcher path to display
78       *
79       * @throws IllegalArgumentException if the argument doesn't comply with the above limitations
80       */
81      public void setErrorPage(String errorPage) {
82          if ((errorPage != null) && !errorPage.startsWith("/")) {
83              throw new IllegalArgumentException("errorPage must begin with '/'");
84          }
85  
86          this.errorPage = errorPage;
87      }
88  }