GWT防止实际设置Cookie的Set-Cookie HTTP标头?

时间:2011-06-14 23:31:13

标签: http gwt cookies

我是GWT noob,但我正在与比我更先进的其他人合作,我们无法弄清楚为什么服务器作为Set-Cookie HTTP标头返回的cookie实际上并未在浏览器中设置。

我使用具有身份验证调用的Tomcat编写了一个服务器。我用HTML编写了一个虚拟网站,它使用Web表单向服务器发送带有身份验证信息的请求,并接收包含Set-Cookie标头的响应。这一切都有效。然后它在同一页面上有一个不同形式的第二个按钮,它向我的服务器发送一些不同的请求和一些表单数据,浏览器会按预期自动将cookie注入标题。因此,对于第二次调用,服务器可以从请求中提取cookie头并验证请求。这一切都很有效。

现在,对于我们开发的测试GWT应用程序,我使用了在开发新的GWT应用程序时自动生成的代码(无AppEngine),并在客户端的EntryPoint类上以下列方式对其进行了修改。我删除了TextBox以输入我的名字和GWT RPC调用。我修改了MyHandler,以便它不再实现KeyPressedListener或其他任何东西并实现RequestCallback。我编辑了onClick的内容以创建一个新的RequestBuilder,它发送带有身份验证信息的POST。到目前为止,这一切都正常,因为我可以在我的服务器上查看日志,它接收请求,处理它,并将身份验证cookie放在响应中。使用Firebug,我可以看到响应包含带有必要cookie信息的Set-Cookie标头。但是,浏览器从未实际保存此信息。不出所料,随后对服务器的调用不包括cookie。

GWT在部署时只编译成JavaScript,对吗?并且JavaScript无法在HTTP响应和浏览器之间注入自己吗?我检查了Response对象,该对象是来自RequestCallback接口的onResponseReceived()调用的参数,除了通过getHeaders()调用之外,它不包含任何访问cookie的方法。但是,我已经抛弃了这个调用的结果,并且它在那里不存在。无论如何,浏览器至少应该在代码之前访问HTTP头,并且应该在将代码交给GWT之前抓取并设置cookie值。我不仅是GWT的新手,我是大多数HTTP客户端开发的新手,但我是否真的远远超出了轨道?

谢谢,

约翰

编辑:

这是我最终得到的代码。我没有改变项目中的任何其他内容。

public void onModuleLoad() {
        final Button loginButton = new Button("Login");
        final Button requestBuilderButton = new Button("Campaign Read");
        final Label errorLabel = new Label();

        // Add the nameField and sendButton to the RootPanel
        // Use RootPanel.get() to get the entire body element
        RootPanel.get("sendButtonContainer").add(loginButton);
        RootPanel.get("sendButtonContainer").add(requestBuilderButton);
        RootPanel.get("errorLabelContainer").add(errorLabel);

        // Create the popup dialog box
        final DialogBox dialogBox = new DialogBox();
        dialogBox.setText("Remote Procedure Call");
        dialogBox.setAnimationEnabled(true);
        final Button closeButton = new Button("Close");
        // We can set the id of a widget by accessing its Element
        closeButton.getElement().setId("closeButton");
        final Label textToServerLabel = new Label();
        final HTML serverResponseLabel = new HTML();
        VerticalPanel dialogVPanel = new VerticalPanel();
        dialogVPanel.addStyleName("dialogVPanel");
        dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
        dialogVPanel.add(textToServerLabel);
        dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
        dialogVPanel.add(serverResponseLabel);
        dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
        dialogVPanel.add(closeButton);
        dialogBox.setWidget(dialogVPanel);

        // Add a handler to close the DialogBox
        closeButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                dialogBox.hide();
            }
        });

        // Create a handler for the sendButton and nameField
        class LoginHandler implements ClickHandler, RequestCallback {
            /**
             * Fired when the user clicks on the sendButton.
             */
            public void onClick(ClickEvent event) {
                dialogBox.show();

                serverResponseLabel.setText(Cookies.getCookie("auth_token"));

                final String url = "http://localhost:8080/app/user/auth_token";
                RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
                builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
                StringBuilder parameters = new StringBuilder();
                parameters.append("user=username&password=password&client=gwt");
                try {
                    builder.sendRequest(URL.encode(parameters.toString()), this);
                }
                catch(RequestException e) {
                    serverResponseLabel.setText(e.toString());
                }
            }

            public void onError(Request request, Throwable exception) {
                serverResponseLabel.setText("Failure.");
            }

            public void onResponseReceived(Request request, Response response) {
                textToServerLabel.setText(Integer.toString(response.getStatusCode()));
                serverResponseLabel.setText(serverResponseLabel.getText() + Cookies.getCookie("auth_token"));
            }
        };

        class CampaignReadHandler implements ClickHandler, RequestCallback {
            public void onClick(ClickEvent event) {
                dialogBox.show();

                final String url = "http://localhost:8080/app/campaign/read";
                RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
                builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
                StringBuilder parameters = new StringBuilder();
                parameters.append("output_format=short&client=gwt&campaign_urn_list=urn:andwellness:nih");
                try {
                    builder.sendRequest(URL.encode(parameters.toString()), this);
                }
                catch(RequestException e) {
                    serverResponseLabel.setText(e.toString());
                }
            }

            public void onError(Request request, Throwable exception) {
                serverResponseLabel.setText("Failure.");
            }

            public void onResponseReceived(Request request, Response response) {
                textToServerLabel.setText(Integer.toString(response.getStatusCode()));
                serverResponseLabel.setText(response.getText());
            }
        };

        // Add a handler to send the name to the server
        LoginHandler loginHandler = new LoginHandler();
        loginButton.addClickHandler(loginHandler);

        CampaignReadHandler campaignReadHandler = new CampaignReadHandler();
        requestBuilderButton.addClickHandler(campaignReadHandler);
    }

2 个答案:

答案 0 :(得分:1)

这是 browsers 的预期行为:http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method(GWT的Response#getHeaders只调用getAllResponseHeaders并解析字符串。)

如果你想获得cookie,你必须使用cookies对象(GWT中的Cookies类);这显然会过滤掉httponly个Cookie。

答案 1 :(得分:0)

如果您使用RequestBuilder联系可能是问题的RPC servlet。特别是如果您在请求中使用的主机不同于浏览器中的主机。

说导航到http://localhost/app

但您的RequestBuilder会为http://machinename/app/servlet.

生成请求

如果您只使用不带RequestBuilder的RPC,则不应该遇到这些问题。

如果您使用的是RequestBuilder,则可能需要通过setting that particular header手动提供Cookie

在浏览器客户端开发中,cookie是以主机名为基础处理的。