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

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

问题描述

我有非常简单的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参数。
选择正确可以得到正确的结果(字符串'测试:文本测试'打印在serwer的控制台上)。

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.

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

例如:当我发送的POST数据与显示的HTML表单相同但具有不同的'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客户端以编程方式提交JSF表单,例如 java.net.URLConnection 或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 ,或者在配置错误的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

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

最后发送POST请求在 /pages/main/main.smnet 上正好包含那些请求参数(以及 JSESSIONID cookie!)。但要小心,(可怜的)JSF开发人员可能会跳过例如来自< h:commandButton> id =sampleButton然后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网站通常也会为REST前端使用单独的JAX-RS应用程序。

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

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

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