Prevent the user from making a GET request to a page
-
29-09-2019 - |
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
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:
In the constructor of the request scoped bean associated with
b.jsf
check for postback byResponseStateManager#isPostback()
and then redirect accordingly usingExternalContext#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.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 byHttpServletRequest#getServletPath()
andgetMethod()
respectively and the redirect can be done usingHttpServletResponse#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 theFilter
inweb.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?