【问题标题】:GWT Preventing Set-Cookie HTTP Header from Actually Setting Cookie?GWT 防止 Set-Cookie HTTP 标头实际设置 Cookie?
【发布时间】:2011-06-14 23:31:12
【问题描述】:

我是一个 GWT 菜鸟,但正在与比我更高级的其他人一起工作,我们无法弄清楚为什么服务器作为 Set-Cookie HTTP 标头返回的 cookie 实际上没有在浏览器中设置。

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

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

GWT 在部署时只是编译成 JavaScript,对吗?并且 JavaScript 不能在 HTTP 响应和浏览器之间注入自己,可以吗?我已经检查了作为来自 RequestCallback 接口的 onResponseReceived() 调用的参数的 Response 对象,它不包含任何访问 cookie 的方法,除非通过 getHeaders() 调用。不过,我已经转储了这个调用的结果,并且它不存在。无论如何,浏览器至少应该在代码之前访问 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);
    }

【问题讨论】:

    标签: http gwt cookies


    【解决方案1】:

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

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

    【讨论】:

    • 我理解并同意。作为客户,我不应该对 Set-Cookie 标头负责。浏览器应该捕捉到这一点,设置 cookie,然后将其余的标题传递给我。当我使用纯 HTML 以及使用带有足够 HTML 来调用 JavaScript 的 JavaScript 时,它按预期工作。当我使用 GWT 对我的服务器进行 POST 时,一切似乎都完全一样。 GWT 没有得到它一开始就不应该收到的 Set-Cookie 标头。但是,就像 Set-Cookie 不在响应中一样。但是,我已经证实它实际上已被退回。
    • 如何检查是否设置?你确定Set-Cookie 是正确的(尤其是域和路径)?
    • 我通过进入浏览器并检查 cookie 来检查它。另外,我正在运行 Firebug,它会告诉我何时设置了新的 cookie。我知道它正在发送,因为它可以按预期与我创建的仅 HTTP 示例页面以及仅 JavaScript(调用 JavaScript 的最低 HTML 除外)页面一起工作。此外,Firebug 将其显示在响应标头中,浏览器将其显示为存储的 cookie。即使我做了 GWT 版本,Firebug 仍然会显示它,但浏览器不会设置它并且 GWT(如预期的那样)没有得到它。
    【解决方案2】:

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

    说导航到http://localhost/app

    但是您的 RequestBuilder 为 http://machinename/app/servlet. 构建了一个请求

    如果您只是使用没有 RequestBuilder 的 RPC,您应该不会遇到这些问题。

    如果您使用 RequestBuilder,您可能必须通过 setting that particular header 手动提供 cookie

    在浏览器客户端开发中,cookie 基于主机名进行处理。

    【讨论】:

    • 据我所知,在 GWT 意义上没有 RPC 发生。我正在使用 RequestBuilder 调用对 GWT 一无所知的服务器。至于构建的 GWT 服务器,我相信它正在运行,但它永远不会收到任何 RPC 调用。我将发布客户端代码以提供更好的想法。
    • 是的,我认为您需要在 RequestBuilder 中手动处理 cookie 标头。
    • 您也可以尝试 [Cookies.setCookie] (google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/…, java.lang.String)),但由于您使用的是 RequestBuilder,这可能是一个很长的机会。
    • 我可以,如果我可以从响应中获取 Cookie 并将其存储在本地。然后,希望浏览器将其附加到所有后续消息中。问题是,我无法访问 Cookie。返回给我的 Response 对象不包含任何 Cookie 访问器,只有一个 get headers 访问器。但是,此调用返回的标头与服务器返回给客户端的标头不同,包括最重要的 Set-Cookie 标头。
    • 我已经能够从 ResponseCallback 中获取 Set-Cookie 标头:@Override public void onResponseReceived(final Request request, final Response response) { String headersString = ""; for (final Header header : response.getHeaders()) { if (header != null) { headersString = headersString + header.getName() + ":" + header.getValue() + "/n"; } } GWT.log(headersString, null); }
    猜你喜欢
    • 2020-08-16
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 2019-11-12
    • 2017-07-01
    • 1970-01-01
    相关资源
    最近更新 更多