谷歌应用引擎和CORS

13

我有一个简单的应用程序(Java servlet),托管在GAE上。该应用程序返回JSON数据。我已在servlet中将标头信息设置如下:

resp.setContentType("application/json");
resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
resp.setHeader("Access-Control-Allow-Credentials", "true");

当我直接在应用引擎上访问该URL时,以下是标头信息:

Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:---------.appspot.com
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko)         Chrome/18.0.1025.162 Safari/535.19
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Cache-Control:private
Content-Encoding:gzip
Content-Length:340
Content-Type:application/json; charset=ISO-8859-1
Date:Sat, 28 Apr 2012 19:14:58 GMT
Server:Google Frontend
Vary:Accept-Encoding

但是当我尝试从不同的域访问该URL时,我收到以下响应:

Request Method:OPTIONS
Status Code:500 Internal Server Error
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, x-requested-with, accept
Access-Control-Request-Method:GET
Connection:keep-alive
Host:----------.appspot.com
Origin:http://--------------.com
Referer:http://-------------.com/map/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19
Response Headersview source
Content-Length:466
Content-Type:text/html; charset=UTF-8
Date:Sat, 28 Apr 2012 19:15:14 GMT
Server:Google Frontend

这里是具体的错误信息:

XMLHttpRequest cannot load http://----------.appspot.com/Locations. Origin http://-------------.com is not allowed by Access-Control-Allow-Origin.

尝试访问GAE URL的代码如下:

$.getJSON("http://---------appspot.com/Locations",function(result){
    for (i=0; i < result.length; i++)
任何帮助将不胜感激。

你的应用程序返回了一个500错误,这可能意味着它抛出了一个未捕获的异常。检查日志以查明原因。 - Nick Johnson
3个回答

11

您需要覆盖标准的HttpServlet.doOptions()方法以支持正确的预检请求处理

@Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
{ 
    // pre-flight request processing
    resp.setHeader("Access-Control-Allow-Origin", "*");
    resp.setHeader("Access-Control-Allow-Methods", SUPPORTED_METHODS);
    resp.setHeader("Access-Control-Allow-Headers", SUPPORTED_HEADERS);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
{
   resp.setHeader("Access-Control-Allow-Origin", "*");
   resp.setContentType("application/json");

   // implementation...
}

这里可以找到一篇很棒的文章,用例子解释了CORS:这里


3
看起来您的请求在 预检请求 上出现问题,因为服务器响应了500(应该响应200 + 特定标头)当被请求 OPTIONS <URL>
您可能需要查看 HTML5rocks CORS教程,特别是添加CORS支持到服务器,在那里预检请求被解释( OPTIONS <url> 请求,您的应用程序无法回复200 + 必需的标头)。

1
这是另一种解决方案(适用于我):
  1. 在Java App Engine项目中配置CORS支持:

使用mvn将以下内容放入您的pom.xml文件中:

<!-- CORS Support for Jetty -->
<dependency>
    <artifactId>jetty-servlets</artifactId>
    <groupId>org.eclipse.jetty</groupId>
    <version>9.2.22.v20170606</version>
</dependency>

或者通过已下载的Jar文件:jetty-servlets.jar,将其放置在您的WEB-INF/lib目录下。
  1. 配置您的web.xml文件:

    <filter> <filter-name>cross-origin</filter-name> <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class> <init-param> <param-name>allowedOrigins</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>allowedMethods</param-name> <param-value>GET,POST,HEAD</param-value> </init-param> <init-param> <param-name>allowedHeaders</param-name> <param-value>X-Requested-With,Content-Type,Accept,Origin</param-value> </init-param> </filter> <filter-mapping> <filter-name>cross-origin</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

也许您需要将allowedOrigins字段值更改为自定义URL。

这就是全部,构建并愉快编码。

如需更多信息: 如何将Access-Control-Allow-Origin添加到jetty服务器中


如果我们没有web.xml文件会怎么样? - Prasanna
web.xml文件对于Java Web应用程序是必要的。 - Heberth
在最新的servlet技术中,我们不需要维护web.xml文件,而是可以通过“@WebServlet”、“@WebListener”等进行注释。 - Prasanna
哦,我明白了,那么你需要知道如何为CORS设置注解。 - Heberth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接