Question

I am sorry if my question does not make any sense. So here is what I have: 2 pages, A.jsf and B.jsf. When I press a button in A.jsf, the code set the value of an object and redirect to B.jsf. Contain of B.jsf will depend on which object I set in A.jsf (which depend on which button I click). Therefore, I dont want to allow the user to type this on the web browser

http://myhost:myport/myproject/B.jsf

and get directly to B.jsf. So, no GET request to B.jsf, only POST. And if I see GET request to B.jsf, I redirect to A.jsf. I feel like the solution is inside web.xml.
btw, I am using Netbean 6.8 and java EE 6

EDIT Here is the solution. Thanks to BalusC
MyFilter.java

package org.xdrawings.filter;

public class MyFilter implements Filter{

    private FilterConfig filterConfig = null;

    public void destroy(){}

    public void init(FilterConfig filterConfig){
        this.filterConfig = filterConfig;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse res = (HttpServletResponse) response;
        if("GET".equals(req.getMethod()) && "/B.jsf".equals(req.getServletPath())){
            res.sendRedirect("A.jsf");
        }else {
            chain.doFilter(request, response);
        }
    }
}

then in my web.xml

<filter>
    <filter-name>My Filter</filter-name>
    <filter-class>org.xdrawings.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>My Filter</filter-name>
    <url-pattern>*.jsf</url-pattern>
</filter-mapping>

All credits go to BalusC

Was it helpful?

Solution

Yes, as you guessed, this can be controlled from in the web.xml. You need to declare a security-constraint on an url-pattern of /b.jsf with http-method of GET, along with an empty auth-constraint.

<security-constraint>
    <display-name>Prevent GET requests on the b.jsf file</display-name>
    <web-resource-collection>
        <web-resource-name>The b.jsf file</web-resource-name>
        <url-pattern>/b.jsf</url-pattern>
        <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint />
</security-constraint>

This however shows a HTTP 403 error. This doesn't (and can't) redirect to a.jsf (at least, not without supplying a custom 403 error page with the necessary checks, but that's plain ugly). If the redirect is mandatory, other solutions are available:

  1. In the constructor of the request scoped bean associated with b.jsf check for postback by ResponseStateManager#isPostback() and then redirect accordingly using ExternalContext#redirect().

    FacesContext context = FacesContext.getCurrentInstance();
    if (!context.getRenderKit().getResponseStateManager().isPostback(context)) {
        context.getExternalContext().redirect("a.jsf");
    }
    

    If you're already on JSF 2.0, you can also use the convenience method FacesContext#isPostback() instead, which is less typing.

  2. Or as a more high-level approach, create a Filter which does exactly the task. The requested page and the HTTP method can be obtained by HttpServletRequest#getServletPath() and getMethod() respectively and the redirect can be done using HttpServletResponse#sendRedirect().

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    if ("GET".equals(req.getMethod()) && "/b.jsf".equals(req.getServletPath())) {
       res.sendRedirect("a.jsf");
    } else {
       chain.doFilter(request, response);
    }
    

    This can be more easily extended for future methods and pages which you can configure as under each init-param of the Filter in web.xml.

OTHER TIPS

Is there something wrong with making B.jsf check for the value set in A.jsf, and issue a redirect if it's not present?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top