GWS与XS。没有POST,只是OPTIONS。加载已取消

时间:2013-04-23 08:18:11

标签: gwt post xss rpc cors

我遇到了GWT应用程序的问题,这个问题相当简单,但是使用gwt的Cross-Site-Scripting机制和GWT-RPC(Async-Interface)。

问题是,浏览器只将OPTIONS命令发送到RPC-Backend而不是POST。因此数据永远不会到达服务器。这是客户端 - 服务器通信的捕获:

来自GWT-Client

OPTIONS /contact/contact/dispatchService HTTP/1.1
Host: svr3.dmz.mycompany.com:8380
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://www.mycompany.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31
Access-Control-Request-Headers: x-gwt-module-base, x-gwt-permutation, origin, content-type
Accept: */*
Referer: http://www.mycompany.com/contact.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

从服务器

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Allow: POST, TRACE, OPTIONS
Content-Length: 0
Date: Tue, 23 Apr 2013 07:13:06 GMT

但是没有数据通过POST发送。

在我的module.gwt.xml中,我有以下使用xs-Linker的行:

<inherits name="com.google.gwt.core.Core" />
<add-linker name="xs" />

不幸的是,我也尝试过xsiframe,结果相同。

当我直接从同一台服务器调用GWT-Application而没有跨站点脚本时,一切正常:

POST /contact/contact/dispatchService HTTP/1.1
Host: svr3.dmz.mycompany.com:8380
Connection: keep-alive
Content-Length: 273
X-GWT-Module-Base: http://svr3.dmz.mycompany.com:8380/contact/contact/
X-GWT-Permutation: 5BE2BF501B916E292DCA5282B8B896AE
Origin: http://svr3.dmz.mycompany.com:8380
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31
Content-Type: text/x-gwt-rpc; charset=UTF-8
Accept: */*
Referer: http://svr3.dmz.mycompany.com:8380/contact/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __utma=179080955.1318578617.1360141977.1366109245.1366612633.29; __utmc=179080955; __utmz=179080955.1366104741.27.5.utmcsr=www.mycompany.com|utmccn=(referral)|utmcmd=referral|utmcct=/index.html

从服务器

7|0|9|http://svr3.dmz.mycompany.com:8380/contact/contact/|C4C9C36F0F0B498822C3C822496B3301|com.mycompany.contact.client.DispatchService|dispatch|com.mycompany.contact.client.DispatchService$Message/2078545930||lastname@mycompany.com|Direct via 
svr3.|givenname|1|2|3|4|1|5|5|6|7|8|9|6|HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Disposition: attachment
Content-Type: application/json;charset=utf-8
Content-Length: 12
Date: Tue, 23 Apr 2013 07:15:44 GMT

//OK[[],0,7]

Web应用程序在通过mod_jk连接的Apache2后面的Tomcat6上运行。

知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

这称为预检请求,当您执行跨源请求时(由于遗留原因有一些例外),浏览器会先与服务器核实Webapp是否为允许POST。

您必须在服务器端处理OPTIONS请求并使用相应的Access-Control-Allow-Origin标头(可能还有Access-Control-Max-AgeAccess-Control-Allow-Headers等)进行回复。

请参阅http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0

请注意,这显然只适用于支持CORS的浏览器,因为CORS排除了很多人(IE仅支持从IE10开始的CORS,不幸的是还不是主流):http://caniuse.com/cors
另请参阅https://developers.google.com/web-toolkit/doc/latest/FAQ_Server#SOP,_GWT,_and_XMLHTTPRequest_Calls

使用xs链接器(BTW,你现在应该更喜欢xsiframe链接器,doc有点过时了)只修复了脚本的加载,它没有覆盖对服务器的请求。您可以使用与路由对RPC服务所在服务器的请求的HTML主机页面相同的来源使用代理(servlet,脚本,服务器配置等)。实际部署;见https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication#DevGuideRPCDeployment

答案 1 :(得分:0)

基于来自Thomas Broyer的信息,我设法通过添加CORS支持过滤器解决了这个问题:

首先我将它添加到我的pom.xml中:

    <dependency>
        <groupId>com.thetransactioncompany</groupId>
        <artifactId>cors-filter</artifactId>
        <version>1.3.2</version>
    </dependency>

然后将其添加到我的web.xml:

<filter>
    <!-- The CORS filter with parameters -->
    <filter-name>CORS</filter-name>
    <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>

    <!-- Note: All parameters are options, if ommitted CORS Filter
         will fall back to the respective default values.
      -->
    <init-param>
        <param-name>cors.allowGenericHttpRequests</param-name>
        <param-value>true</param-value>
    </init-param>

    <init-param>
        <param-name>cors.allowOrigin</param-name>
        <param-value>*</param-value>
    </init-param>

    <init-param>
        <param-name>cors.allowSubdomains</param-name>
        <param-value>false</param-value>
    </init-param>

    <init-param>
        <param-name>cors.supportedMethods</param-name>
        <param-value>GET, HEAD, POST, OPTIONS</param-value>
    </init-param>

    <init-param>
        <param-name>cors.supportedHeaders</param-name>
        <param-value>Content-Type, X-Requested-With, x-gwt-module-base, x-gwt-permutation, origin</param-value>
    </init-param>

    <init-param>
        <param-name>cors.exposedHeaders</param-name>
        <param-value>X-Test-1, X-Test-2</param-value>
    </init-param>

    <init-param>
        <param-name>cors.supportsCredentials</param-name>
        <param-value>true</param-value>
    </init-param>

    <init-param>
        <param-name>cors.maxAge</param-name>
        <param-value>3600</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CORS</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

有关过滤器的详细信息,请参阅here

注意:我已经使用IE 8测试了这个解决方案,不幸的是,正如预期的那样,不能使用IE 8 。我还没有用更新的版本测试它,但由于IE 8仍然存在,我必须通过mod_jk将rpc-servlet包含在同一个原始网站中。