我是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);
}
答案 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是以主机名为基础处理的。