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 }