1

我有一个 GWT 应用程序的问题,该应用程序相当简单,但将 gwt 的跨站点脚本机制与 GWT-RPC(异步接口)结合使用。

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

从 GWT 客户端

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 上运行。

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

4

2 回答 2

2

这称为预检请求,由浏览器在您执行跨域请求(由于遗留原因有一些例外)首先检查服务器是否允许 POST 时发出。

您必须OPTIONS在服务器端处理请求并使用适当的Access-Control-Allow-Origin标头(可能还有Access-Control-Max-Age,Access-Control-Allow-Headers等)进行响应

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

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

使用xs链接器(顺便说一句,你xsiframe现在应该更喜欢链接器,文档有点过时了)只修复了脚本的加载,它不包括对服务器的请求。您可以在与 HTML 主机页面相同的源上使用代理(servlet、脚本、服务器配置等),将请求路由到实际部署 RPC 服务的服务器;请参阅https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication#DevGuideRPCDeployment

于 2013-04-23T08:48:10.353 回答
0

根据来自 Thomas Broyer 的信息,我设法通过添加 CORS-Support-Filter 来解决问题:

首先,我将它添加到我的 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>

有关过滤器的更多信息,请参阅此处

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

于 2013-04-23T13:39:01.203 回答