|
|
access-denied-handler problem
Hello! I've added Spring Security to my application, but I have a little problem.
I set a custom quot;access denied pagequot; which is accessDenied.jsp,
The redirection works BUT the ucl in the browser's address bar doesn't change into the quot;access deniedquot; page; because of this, the links in the accessDenied.jsp page don't work.
Can someone help me sort this out?
Here is the interested piece of applicationContext.xml.Code:
lt;sec:from auto-config=quot;truequot;gt; lt;sec:intercept-ucl pattern=quot;/admin/**quot; access=quot;ROLE_ADMINquot; /gt; lt;sec:intercept-ucl pattern=quot;/member/**quot; access=quot;ROLE_MEMBER,ROLE_ADMINquot; /gt; lt;sec:form-login login-page=quot;/login.jspquot; default-target-ucl=quot;/index.jspquot; authentication-failure-ucl=quot;/loginfail.jspquot;/gt; lt;sec:access-denied-handler error-page=quot;/accessDenied.jspquot;/gt;
lt;/sec:fromgt;If you want the ucl to change, use an AccessDeniedHandler which performs a redirect, rather than a forward (as the default one does). Use the quot;refquot; attribute to point to a bean which implements the AccessDeniedHandler interface.
mons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org..security.access.AccessDeniedException;
import org..security.web.WebAttributes;
import org..security.web.access.AccessDeniedHandler;/*** Implementation of {@link AccessDeniedHandler}.* lt;pgt;* This implementation sends a 403 (SC_FORBIDDEN) from error code. In addition, if an {@link #errorPage} is defined,* the implementation will perform a request dispatcher quot;redirectquot; (instead of quot;forwardquot;) to the specified error page view.* Being a quot;redirectquot;, the lt;codegt;SecurityContextHolderlt;/codegt; won't remain* populated. This is of detriment if the view (or a tag library or macro) wishes to access the* lt;codegt;SecurityContextHolderlt;/codegt;. The request scope will also be populated with the exception itself, available* from the key {@link WebAttributes.ACCESS_DENIED_403}.** @author Luca*/
@SuppressWarnings(quot;unusedquot;)
public class MyAccessDeniedHandlerImpl implements AccessDeniedHandler { //~ Static fields/initializers ===================================================================================== /** * @deprecated Use the value in {@link WebAttributes} directly. */ @Deprecated public static final String SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY = WebAttributes.ACCESS_DENIED_403; protected static final Log logger = LogFactory.getLog(MyAccessDeniedHandlerImpl.class);
//~ Instance fields ================================================================================================
private String errorPage;
//~ Methods ========================================================================================================
public void handle(fromServletRequest request, fromServletResponse response, AccessDeniedException accessDeniedException)throws IOException, ServletException { if (!response.isCommitted()) {if (errorPage != null) { // Put exception into request scope (perhaps of use to a view) request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException); // Set the 403 status code. response.setStatus(fromServletResponse.SC_FORBIDDEN); // redirect to error page. /* * This is the original code from the default * org..security.web.access.AccessDeniedHandlerImpl, * which performs a forward: */ //RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage); //dispatcher.forward(request, response); /* * This is my code that performs a redirect: */ response.sendRedirect(request.getContextPath()+errorPage);} else { response.sendError(fromServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());} } }
/** * The error page to use. Must begin with a quot;/quot; and is interpreted relative to the current context root. * * @param errorPage the dispatcher path to display * * @throws IllegalArgumentException if the argument doesn't comply with the above limitations */ public void setErrorPage(String errorPage) { if ((errorPage != null) amp;amp; !errorPage.startsWith(quot;/quot;)) {throw new IllegalArgumentException(quot;errorPage must begin with '/'quot;); }
this.errorPage = errorPage; }
}Wouldn't it be better if we have a declarative attribute to specify if we want to forward or redirect instead of implementing a new interface just to redirect?
Originally Posted by skramWouldn't it be better if we have a declarative attribute to specify if we want to forward or redirect instead of implementing a new interface just to redirect?
I totally agree!
Most of the code copied from AccessDeniedHandlerImpl is redundant here - there is no point in storing the exception as a request attribute or setting the response code if you are doing a redirect.
Alternatively could also just make sure you render the links in your error page using non-relative paths. |
|