防止用户向页面发出GET请求

3
抱歉如果我的问题没有任何意义。以下是我的情况:2个页面,A.jsfB.jsf。当我在A.jsf中按下按钮时,代码设置一个object的值并重定向到B.jsfB.jsf的内容将取决于我在A.jsf中设置的对象(这取决于我点击哪个按钮)。因此,我不想允许用户在web浏览器中键入此内容

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

并直接进入B.jsf。因此,不能向B.jsf发送GET请求,只能发送POST请求。如果我看到对B.jsf的GET请求,则会重定向到A.jsf。我觉得解决方案在web.xml内。
顺便说一句,我正在使用Netbean 6.8和Java EE 6。

编辑 这里是解决方案。感谢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);
        }
    }
}

然后在我的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>

所有功劳归于BalusC

2个回答

7

是的,正如你所猜测的那样,这可以从web.xml中进行控制。您需要在/b.jsfurl-pattern上声明一个security-constraint,使用GEThttp-method,以及一个空的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>

然而,这显示了一个HTTP 403错误。这不会(也不能)重定向到a.jsf(至少不提供必要检查的自定义403错误页面,但那样很丑陋)。如果必须重定向,则有其他解决方案:

  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.


1
让我惊讶的是你对Web开发的了解。你的第一个方法很好用。但是,我也想学习第二种方法,因为我经常听说人们创建过滤器,但不确定它是什么。所以看起来你正在创建一个自定义的Filter,并通过web.xml告诉项目使用该过滤器,对吗?让我试一下,然后再回复你。非常感谢! - Thang Pham
我实现了你的第二种方法,但是我有几个问题,你能看一下我的更新帖子来看我的实现吗? - Thang Pham
1
过滤器可以映射在<url-pattern>/*上,或者更具体地是*.jsf,甚至更具体地是/b.jsf(然后在if块中删除不必要的检查)。 <init-param> 是可选的。 如果您定义了任何内容,则可以通过 FilterConfig#getInitParameter() 方法在init()方法中使用它,并将其分配为实例变量,以在doFilter()逻辑中进一步使用,例如页面名称的逗号分隔字符串等。 - BalusC
谢谢。我已经成功获取了它。但是我认为 res.sendRedirect("/a.jsf"); 实际上应该是 res.sendRedirect("a.jsf"); - Thang Pham

1

在编写程序时,让B.jsf检查A.jsf中设置的值是否存在,并在不存在时发出重定向,这样做有什么问题吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接