如何在不使用 HTML 表单的情况下以编程方式将 POST 请求发送到 JSF 页面? [英] How to programmatically send POST request to JSF page without using HTML form?

查看:24
本文介绍了如何在不使用 HTML 表单的情况下以编程方式将 POST 请求发送到 JSF 页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的 JSF bean,如下所示:

I have very simple JSF bean like shown below:

import org.jboss.seam.annotations.Name;

@Name(Sample.NAME)
public class Sample {

    public static final String NAME="df";

    private String text = "text-test";

    public void sampleM(){
        System.out.println("Test: "+text);
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

与这个组件相连的JSF表单:

And JSF form connected with this component:

<h:form id="sampleForm">
        <h:commandButton id="sampleButton" action="#{df.sampleM()}" value="ok" />
</h:form>

现在,我想以编程方式向此表单发送 POST 请求.

Now, I would like to programmatically send POST request to this form.

根据我的调查,这里的关键是 POST 参数.正确选择会给出正确的结果(字符串 'Test: text-test' 打印在服务器的控制台上).

According to my investigation the key here are POST parameters. Selected properly gives proper results (String 'Test: text-test' is printed on serwer's console).

所以问题是:我应该如何选择正确的 POST 数据?

上面显示的 JSF 表单生成此 HTML 表单:

JSF form shown above produces this HTML form:

<form id="sampleForm" name="sampleForm" method="post" action="/pages/main/main.smnet" enctype="application/x-www-form-urlencoded">
    <input type="hidden" name="sampleForm" value="sampleForm" />
    <input id="sampleForm:sampleButton" type="submit" name="sampleForm:sampleButton" value="ok" />
    <input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id65" autocomplete="off" />
</form>

所以这些参数是正确的.

So these parameters are corrent.

但是我怎样才能找出哪些参数(名称和值)对于任何其他组件来说是足够的?

例如:当我发送与显示的 HTML 表单相同的 POST 数据但具有不同的 'javax.faces.ViewState' 参数值时,将不会执行组件方法.

For example: when I send POST data the same like in shown HTML form but with different 'javax.faces.ViewState' parameter value, component method will not be executed.

推荐答案

我知道您基本上是在问如何使用某些 HTTP 客户端(例如 java.net.URLConnection)以编程方式提交 JSF 表单或 Apache HttpComponents 客户端,对吗?

I understand that you're basically asking how to submit a JSF form programmatically using some HTTP client such as java.net.URLConnection or Apache HttpComponents Client, right?

您需要先发送 GET 请求,并确保跨请求维护相同的 HTTP 会话(基本上,JSESSIONID cookie).让您的 HTTP 客户端从第一个 GET 请求的响应中提取 Set-Cookie 标头,从中获取 JSESSIONID cookie 并将其作为 Cookie 后续 POST 请求的标头.这将在服务器端维护 HTTP 会话,否则 JSF 会将其视为View Expired",它可能会在适当配置的 JSF Web 应用程序上返回带有 ViewExpiredException 的 HTTP 500 错误页面,或者在配置不当的 JSF Web 应用程序表现为页面刷新.

You need to send a GET request first and make sure that you maintain the same HTTP session (basically, the JSESSIONID cookie) across requests. Let your HTTP client extract the Set-Cookie header from the response of the first GET request, obtain the JSESSIONID cookie from it and send it back as Cookie header of subsequent POST requests. This will maintain the HTTP session in the server side, otherwise JSF will treat it as a "View Expired" which may return either on a decently configured JSF web application a HTTP 500 error page with ViewExpiredException, or on a badly configured JSF web application behave as a page refresh.

作为 JSF 的有状态特性和隐含的 CSRF 攻击预防的一部分,表单必须使用有效的 javax.faces.ViewState 值提交,因为客户端已在初始 GET 请求中检索到自身.您还需要确保发送所有其他隐藏字段的 name=value 对,尤其是提交按钮之一.

As part of JSF's stateful nature and implied CSRF attack prevention, the forms must be submitted with a valid javax.faces.ViewState value as the client has retrieved itself on the initial GET request. You also need to make sure that you send the name=value pair of all other hidden fields and particularly the one of the submit button along as well.

因此,如果您的初始 GET 请求将这个 HTML 返回给您

So, if your initial GET request gives you this HTML back

<form id="sampleForm" name="sampleForm" method="post" action="/pages/main/main.smnet" enctype="application/x-www-form-urlencoded">
    <input type="hidden" name="sampleForm" value="sampleForm" />
    <input id="sampleForm:sampleButton" type="submit" name="sampleForm:sampleButton" value="ok" />
    <input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id65" autocomplete="off" />
</form>

然后你需要解析它(Jsoup 可能对此有帮助)并提取以下请求参数:

then you need to parse it (Jsoup may be helpful in this) and extract the following request parameters:

  • sampleForm=sampleForm
  • sampleForm:sampleButton=ok
  • javax.faces.ViewState=j_id65

最后在 /pages/main/main.smnet 上发送一个 POST 请求,并使用这些请求参数(和 JSESSIONID cookie!).但是要小心,(可怜的)JSF 开发人员可能已经跳过了,例如id="sampleButton" 来自 <h:commandButton> 然后 JSF 会自动生成一个看起来像这种格式的 sampleForm:j_id42.您不能对它们进行硬编码,因为该值可能会根据组件在服务器端树中的位置而变化,然后您真的需要将其解析出获得的 HTML.

Finally send a POST request on /pages/main/main.smnet with exactly those request parameters (and the JSESSIONID cookie!). Be careful though, it's possible that a (poor) JSF developer has skipped e.g. id="sampleButton" from the <h:commandButton> and then JSF would autogenerate one which looks like in this format sampleForm:j_id42. You can't hardcode them as the value may change depending on the component's position in the server side tree and you would then really need to parse it out the obtained HTML.

尽管如此,明智的做法是联系网站所有者/管理员并询问是否没有可用于您心目中的任务的 Web 服务 API.将 JSF 应用程序用于 HTML 前端的不错的 Java EE 网站通常也将单独的 JAX-RS 应用程序用于 REST 前端.

Nonetheless, it's wise to contact the site owner/admin and ask if there isn't a web service API available for the task you had in mind. A decent Java EE website which uses a JSF application for a HTML frontend usually also uses a separate JAX-RS application for a REST frontend.

  • How can i programmatically upload a file to a website? (this also concerns JSF)
  • Using java.net.URLConnection to fire and handle HTTP requests

这篇关于如何在不使用 HTML 表单的情况下以编程方式将 POST 请求发送到 JSF 页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆