2011-06-14 43 views
2

我是一個GWT noob,但我正在與比我更高級的其他人一起工作,而且我們無法弄清楚爲什麼服務器返回的Cookie作爲Set-Cookie HTTP標頭實際上並未在瀏覽器中設置。GWT防止Set-Cookie HTTP頭實際上設置Cookie?

我寫了一個使用Tomcat的服務器,它有一個認證調用。我用HTML編寫了一個虛擬網站,它使用Web表單向服務器發送帶有認證信息的請求,並接收包含Set-Cookie頭的響應。這一切都有效。然後,它會在同一頁面上以不同形式顯示第二個按鈕,並使用某些表單數據向我的服務器發送不同的請求,並且瀏覽器會按照預期自動將cookie注入到標題中。因此,第二次調用的服務器可以將cookie標頭從請求中拉出並驗證請求。這一切都很有效,而且很棒。

現在,對於我們開發的測試GWT應用程序,我使用了在開發新GWT應用程序(無AppEngine)時自動生成的代碼,並在客戶端的EntryPoint類中通過以​​下方式對其進行了修改。我刪除了輸入我的名字和GWT RPC調用的TextBox。我修改了MyHandler,以便它不再實現KeyPressedListener或其他任何方法,並且實現了RequestCallback。我編輯了onClick的內容以創建一個新的RequestBuilder,它發送帶有驗證信息的POST。到目前爲止,這一切都起作用,因爲我可以在服務器上觀看日誌,並接收請求,處理它,並將身份驗證Cookie放入響應中。使用Firebug,我可以看到響應包含Set-Cookie頭和必要的cookie信息。但是,瀏覽器從不實際保存這些信息。不出所料,隨後對服務器的調用不包括cookie。

GWT在部署時剛編譯成JavaScript,是否正確?而JavaScript不能在HTTP響應和瀏覽器之間注入本身嗎?我已經從RequestCallback接口檢查了作爲onResponseReceived()調用參數的Response對象,並且它不包含任何通過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

如果您使用RequestBuilder聯繫可能存在問題的RPC servlet。特別是如果您在請求中使用的是不同的主機,那麼您的瀏覽器中使用的是不同的主機。

說導航到http://localhost/app

但是你RequestBuilder如果你只是使用RPC沒有RequestBuilder你不應該有這些問題,建立了http://machinename/app/servlet.

的請求。

,以及如果你正在使用RequestBuilder你可能必須通過setting that particular header

手動提供餅乾在瀏覽器客戶端的開發餅乾上的主機名的基礎上進行處理。

+0

盡我所知,GWT意義上沒有RPC發生。我正在使用一個RequestBuilder來調用一個對GWT一無所知的服務器。至於構建的GWT服務器,我相信它正在運行,但它永遠不會收到任何RPC調用。我將發佈客戶端代碼以提供更好的想法。 – John 2011-06-15 00:30:14

+0

是的,我認爲你將需要在RequestBuilder中手動處理cookie頭。 – 2011-06-15 01:45:25

+0

您可以試試[Cookies.setCookie](http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/user/client/Cookies.html#setCookie(java.lang。 String,java.lang.String)),但是由於您使用的是RequestBuilder,因此這可能是一個長鏡頭。 – 2011-06-15 01:47:36

1

這是瀏覽器預期的行爲:http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method(GWT的Response#getHeaders簡單地調用getAllResponseHeaders並解析字符串)。

如果你想獲取cookies,你必須使用cookies對象(GWT中的Cookies類);這顯然會過濾掉httponly Cookie。

+0

我理解並同意。作爲客戶端,我不應該對Set-Cookie頭負責。瀏覽器應該抓住這一點,設置cookie,然後將其餘*標題傳給我。而且,當我使用純HTML時,以及當我使用JavaScript和足夠的HTML來調用JavaScript時,它的工作方式與預期相符。當我使用GWT對我的服務器進行POST時,一切看起來都一模一樣。 GWT並沒有得到它本來不應該收到的Set-Cookie頭。但是,這就像Set-Cookie不在響應中。但是,我已經證實它實際上已經返回。 – John 2011-06-24 16:50:27

+0

你如何檢查它是否設置?你確定'Set-Cookie'是否正確(尤其是域和路徑)? – 2011-06-24 17:14:35

+0

我通過進入瀏覽器並檢查cookie來檢查它。另外,我還運行了Firebug,它告訴我何時設置了新的cookie。我知道它正在發送,因爲它按照預期的方式工作,僅使用我創建的僅HTTP樣本頁面以及我創建的僅限JavaScript(除了調用JavaScript的最小HTML)頁面。此外,Firebug將它顯示在響應標題中,瀏覽器將其顯示爲存儲的cookie。即使我做GWT版本,Firebug仍然會顯示它,但瀏覽器不會設置它,並且GWT(如預期的)不會得到它。 – John 2011-06-27 16:20:40