AngularJS无法检测到Access-Control-Allow-Origin头部?

45

我正在本地虚拟主机http://foo.app:8000上运行一个Angular应用程序。 它正在使用$http.post向另一个本地虚拟主机http://bar.app:8000发出请求。

$http.post('http://bar.app:8000/mobile/reply', reply, {withCredentials: true});
在Chrome开发者工具的网络选项卡中,我当然能看到OPTIONS请求,并且响应包括头信息:

在Chrome开发者工具的“网络”标签中,我可以看到OPTIONS请求,响应中包含了该头部信息:

Access-Control-Allow-Origin: http://foo.app:8000
然而,使用POST请求时出现以下错误取消:

请求的资源上没有“Access-Control-Allow-Origin”标头。 因此,不允许访问来源为'http://foo.app:8000'。

有人遇到过这种情况吗? OPTIONS请求的响应中明确包含了Access-Control-Allow-Origin 标头,因此我无法理解为什么POST好像缺少这个标头。

Access-Control-Allow-Credentials 也设置为true 。


你在OPTIONS响应中看到Access-Control-Allow-Methods头吗? - harun
确实。允许所有方法。 - TaylorOtwell
9个回答

47

这是Chrome在本地开发中的一个错误。尝试其他浏览器,然后它就可以工作了。


1
谢谢。在Firefox中运行良好。您有关于这个错误的更多信息吗? - TaylorOtwell
7
不是真正的bug,而是出于安全原因。参见:https://dev59.com/QnA75IYBdhLWcg3wy8Ui - user1469734
1
我在其他浏览器中尝试了一下,它可以工作 @_@ 为什么 Chrome 这么刻薄 :( - Bruno Gomes
当您准备将应用程序部署给更大的受众使用时,您应该怎么做?大多数人使用Chrome,正确处理此问题的方法是什么? - Donald N. Mafa
1
这不是一个解决方案!!!这与CORS有关,而不仅仅是浏览器...它是一种安全约束。您可以在服务器上始终启用CORS。 - Paul Okeke

26

对于想使用Chrome的人来说,有一个解决办法。 这个扩展程序 允许您从任何来源请求带有AJAX的任何网站,因为它向响应添加了'Access-Control-Allow-Origin: *'头。

作为替代方案,您可以将此参数添加到Chrome启动器中:--disable-web-security。请注意,我只会将其用于开发目的,而不是普通的“网络浏览”。有关参考,请参见在标志下运行Chromium

最后提醒一句,在安装第一段中提到的扩展名后,您可以轻松启用/禁用CORS。


额外的好处是,这个非常有用的插件也恰好可以阻止Facebook工作,如果你的软件开发工作流程与我的相似,那么你很可能会以创纪录的时间完成你正在工作的其余部分。 - Chris Rae
没错,@ChrisRae。 - Rui Afonso Pereira
这个扩展似乎消除了错误。但是当我检查请求头时,它添加了Origin: http://evil.com。我不知道这是否有害或无关紧要。 - Isaac Pak

7
我使用AngularJS的$http服务向运行在http://localhost:8090/上的bottle发送请求,但是我必须应用CORS,否则我会收到"请求的资源未包含'Access-Control-Allow-Origin'头部"等请求错误。
from bottle import hook, route, run, request, abort, response

#https://github.com/defnull/bottle/blob/master/docs/recipes.rst#using-the-hooks-plugin

@hook('after_request')
def enable_cors():
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, PUT'
    response.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept'

3

需要从服务器端解决CROS问题。

根据需求创建过滤器以允许访问,并将过滤器添加到web.xml中。

使用spring的示例:

过滤器类:

@Component
public class SimpleFilter implements Filter {

@Override
public void init(FilterConfig arg0) throws ServletException {}

@Override
public void doFilter(ServletRequest req, ServletResponse resp,
                     FilterChain chain) throws IOException, ServletException {

    HttpServletResponse response=(HttpServletResponse) resp;

    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with");

    chain.doFilter(req, resp);
}

@Override
public void destroy() {}

}

Web.xml:

<filter>
    <filter-name>simpleCORSFilter</filter-name>
    <filter-class>
        com.abc.web.controller.general.SimpleFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>simpleCORSFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3
我遇到了完全相同的问题。对于我来说,OPTIONS请求可以通过,但POST请求会显示“中止”。这让我认为浏览器根本没有发出POST请求。Chrome在请求头中说:“警告:显示临时标头”,但没有显示响应头。最后,我转向Firefox进行调试,结果发现我的服务器响应错误,并且响应中没有CORS标头。Chrome实际上收到了响应,但不允许在网络视图中显示响应。

谢谢 - 你帮我解决了问题。我的情况和你一样,我在使用Amazon API网关并从AngularJS中调用它时出现了同样的症状。我缺少一个参数,就像@tacticurv建议的那样,但Chrome暗示它从未进行POST请求,因为CORS的OPTIONS请求明显成功了。我发现的额外陷阱是API网关的有用的“启用CORS”按钮没有完全完成工作。它只向200 OK响应添加了标头,并从400和500错误响应中漏掉了它们。这些错误随后被Chrome检查器忽略了! - charltones
@charltones 自从我发布了那个答案以来,我一直在使用 chrome://net-internals/#events 来检测这样的错误,而不是使用 Firefox。将来知道这一点会很方便。我确实向 Chromium 发送了一个 bug,它曾经被修复过一段时间,但我认为他们又回滚了。https://code.google.com/p/chromium/issues/detail?id=343707 - brain_bacon

2

不要使用 $http.get('abc/xyz/getSomething'),尝试使用$http.jsonp('abc/xyz/getSomething')

     return{
            getList:function(){
                return $http.jsonp('http://localhost:8080/getNames');
            }
        }

2

当你在请求中的参数错误时,也会发生这种情况。在我的情况下,我正在使用一个API,并收到以下消息:

"请求的资源上没有 'Access-Control-Allow-Origin' 头, 因此源头 'null' 不被允许访问.响应的HTTP状态码为401."

当我通过POST请求提交错误的用户名或密码进行登录时。


2
我今天遇到了这个问题。原来是服务器上的一个bug(空指针异常)导致它无法创建响应,但仍生成了200的HTTP状态码。由于状态码为200,Chrome期望得到有效的响应。Chrome首先查找“Access-Control-Allow-Origin”头,但没有找到。然后Chrome取消了请求,Angular给我报错。处理POST请求时出现的错误是OPTIONS成功但POST失败的原因。
简而言之,如果你遇到这个错误,可能是因为服务器在响应POST请求时没有返回任何头信息。

这基本上就是我遇到的问题 - 感谢您的提醒。 - Eamonn Gahan

0
如果你在使用sails.js时遇到了这个问题,只需将cors.js设置为允许包含Authorization头即可解决。

/***************************************************************************
  *                                                                          *
  * Which headers should be allowed for CORS requests? This is only used in  *
  * response to preflight requests.                                          *
  *                                                                          *
  ***************************************************************************/

  headers: 'Authorization' // this line here


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