从 angularjs 调用 REST 服务时本地主机上的 CORS 问题

CORS issue on localhost while calling REST service from angularjs

我正在学习 angularJS 并尝试在我的应用程序中实现它。

我有一个 RESTful WCF 服务托管在本地主机 IIS 上。 它定义了一个 GET 方法来获取文档列表:http://localhost:70/DocumentRESTService.svc/GetDocuments/

现在我正尝试在我的 angular 应用程序中使用此服务并显示数据。 以下是代码: HTML :

<html>
    <script src="../../dist/js/angular/angular.min.js"></script>
    <script src="../../assets/js/one.js"></script>
    <body ng-app="myoneapp" ng-controller="oneAppCtrl">
                {{"Hello" + "AngularJS"}}
        <hr>
        <h1> Response from my REST Service </h1>
        {{hashValue}}

        <hr>
        <h1> Response from w3school REST Service </h1>
        {{names}}


    </body>
</html>

JS:

angular.module('myoneapp', [])
    .controller('oneAppCtrl', function($scope,$http){
        $scope.documentValue = {};

        $http({method: 'GET',
                url: 'http://localhost:70/DocumentRESTService.svc/GetDocuments/',
                headers:
                        {
//                          'Access-Control-Allow-Origin': 'http://localhost'
                        }                   
               })
            .success(function(data){ alert('Success!'); $scope.documentValue=data;})
            .error(function(data){ alert('Error!'); $scope.documentValue=data; alert('Error!' + $scope.documentValue);})
            .catch(function(data){ alert('Catch!'); $scope.documentValue= data;});

        $http.get("http://www.w3schools.com/angular/customers.php")
            .success(function(response) {$scope.names = response.records;});            
});

奇怪的是这段代码在 IE11 中工作得很好,而在 Chrome/Firefox.

中却没有 运行

以下是 chrome 中的响应:(对于我的 REST 服务),而来自 w3schools 的 REST 服务工作得很好。

{"data":null,"status":0,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"url":"http://localhost:70/DocumentRESTService.svc/GetDocuments/","headers":{"Accept":"application/json, text/plain, /"}},"statusText":""}

控制台显示以下错误消息。

XMLHttpRequest 无法加载 http://localhost:70/DocumentRESTService.svc/GetDocuments/。请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源 'file://'。

XMLHttpRequest 无法加载 http://localhost:70/DocumentRESTService.svc/GetDocuments/。请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源'http://127.0.0.1:55969'。

Cross-Origin 请求被阻止:同源策略不允许读取位于 http://localhost:70/DocumentRESTService.svc/GetDocuments/ 的远程资源。这可以通过将资源移动到同一域或启用 CORS 来解决。

这里的问题很少:

  1. 为什么 localhost 或我的 machineName 被认为是 cross-domain 请求?我在同一个域中,不是吗?
  2. 是否需要在我的服务端进行任何更改才能启用此行为?如果是,WCF 服务在哪里?(基于我阅读的内容 here
  3. JSONP 在这种情况下有用吗?如果是,我将如何使用它?它是否适用于需要自定义 headers 的请求?(不确定它是什么,但在重新搜索时发现很多答案都提到了这一点。阅读链接会有所帮助。)

任何帮助或指导都会有所帮助。

P.S:

我可以解决这个问题。 有几种方法可以做到这一点 - 我正在记下我尝试过的所有方法以及它们的参考资料。

回答 问题1.

'Why is localhost or my machineName considered to be a cross-domain request?'

正如@charlietfl 提到的和我研究过的here:不同的端口或子域也被浏览器视为跨域。

回答 问题2.

'Are there any changes required to do at my service end to enable this behavior?'

是的!服务器端本身需要更改。服务器应以

响应请求

Access-Control-Allow-Origin: *

header。这里的 * 可以替换为请求 header 本身或根据您的应用程序要求。优秀的博客 here 解释了使用 WCF REST 服务时的解决方法。您需要向每个服务方法添加以下行 (headers) 以在您的服务方法中启用 CORS。

WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Origin", "*"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Methods", "POST"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Headers", "Content-Type, Accept");

规范here对于在服务器/客户端上启用 CORS 非常有帮助。

问题 3 的答案。

JSONP 主要适用于 GET 请求,不是最可取的用途,而是最推荐启用 CORS。 (我没有深入探索这个领域,但 Wiki & Whosebug article here 非常具有描述性)。

除此之外,出于测试目的,一个不错的 chrome extension here 可能会有所帮助。它可用于确保应用程序存在 CORS 问题。

我为模拟 Ionic 项目(运行 本地)与一些小型 Node.JS Web 服务(也 运行 本地)交互引起的 CORS 问题苦苦挣扎了太久.

看看简短的简单解决方法:Chrome 的插件 AllowControlAllowOrigin。

https://chrome.google.com/webstore/search/cross%20origin?utm_source=chrome-ntp-icon&_category=extensions

只需将单选按钮从红色切换为绿色,就不会再有被阻止的请求、错误或警告! 当然,这是一个临时解决方案,当停止本地测试的时间到来时,您可能不得不提出您的请求 headers。与此同时,这是避免浪费时间处理那些反复出现的烦人问题的好方法。

如果您在访问本地主机中的 REST API 运行 时遇到 AngularJS 应用程序中的 CORS 问题,请检查以下内容:在您的服务器应用程序中添加 CORS 过滤器。就我而言,我在 Spring application

中添加了以下代码
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

public SimpleCORSFilter() {
    log.info("SimpleCORSFilter init");
}

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

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}

在 angularjs 代码中,不要给 URL 像 http://localhost:8080/../。而不是 localhost 给出您的主机 IP 号。

它将正常工作