AngularJS跨域资源共享问题

42

我在200多个网站上搜索(或许有点夸张,但不是很离谱)如何使用AngularJS处理跨域资源共享。我们有一台本地机器运行Web API服务器。我们正在开发一个客户端来调用API获取数据。当我们从服务器运行客户端时,我们可以毫无问题地接收数据。但当我们从另一个域运行时,尝试获取数据会收到一个红色的200响应和一个空白响应。以下是一些代码:

var myApp = angular.module('Project', ['ngResource']);

myApp.config(function($routeProvider){
    $routeProvider.
        when('/new', {templateUrl:'templates/new.html', controller:'EditProjectController'}).
        when('/mobile', {templateUrl:'templates/mobile.html', controller:'ProjectController'}).
        when('/it', {templateUrl:'templates/it.html', controller:'ProjectController'}).
        when('/writing', {templateUrl:'templates/writing.html', controller:'ProjectController'}).
        when('/all', { templateUrl: 'templates/all.html' }).
        when('/login', { templateUrl: 'partials/_login.html' }).
        otherwise({ redirectTo: '/all' });
});
myApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);



myApp.controller('ProjectController', 
function myApp($scope, $http, projectDataService, userLoginService) {
    $http.defaults.useXDomain = true;
    $scope.loadProject = function(){
        projectDataService.getProject(function(project){
            $scope.project = project;
            })


    };
    $scope.loadProject();
}

);

myApp.factory('projectDataService', function ($resource, $q) {
var resource = $resource('http://webapiserver/api/:id', { id: '@id' });
return {
    getProject: function () {
        var deferred = $q.defer();
        resource.query({ id: 'project' },
            function (project) {
                deferred.resolve(project);
            },
            function (response) {
                deferred.reject(response);
            });

        return deferred.promise;
    },
    save: function (project) {
        var deferred = $q.defer();
        project.id = 'project/9';
        resource.save(project,
            function (response) { deferred.resolve(response); },
            function (response) { deferred.reject(response); }
            );
        return deferred.promise;
    }
};
});

我也尝试使用 $http,但我得到了同样的响应(或者说没有响应):

myApp.factory("projectDataService", function ($http) {

return {
    getProject: function (successcb) {
        $http.get("http://webapiserver/api/project").
        success(function (data, status, headers, config) {
            successcb(data);
        }).
        error(function (data, status, headers, config) {

    }
};
});

当我在浏览器中访问提供JSON的URL时,它就会输出数据。 我们在服务器上允许跨域来源,这可以从我的前面的陈述中看出。正如您所看到的,我正在myApp.config中实现头文件覆盖,甚至尝试将其直接放入控制器中...但没有任何区别...

这个任务已经持续了3天。

非常感谢您能帮忙解决。提前致谢。


所以你的GET请求失败了?请显示请求和响应的头信息。如果您在Chrome中打开网络选项卡并包含头部部分中的所有内容,那将是最简单的方法。 - Ray Nicholus
如果您在Chrome的开发者工具中查看XMLHttpRequest(XHR)请求,您能否看到跨域头和选项握手的发生? - Si Robinson
4个回答

11

您可能需要稍微更改您的Web API。我遇到了同样的问题,并撰写了一篇关于如何解决此问题的文章。

我使用Sinatra制作API,我不知道您正在使用哪种语言进行webservices,但我猜您可以应用它。基本上,您需要配置服务器以接受CORS调用,通过定义允许的来源和HTTP方法。

您说您已经在服务器上启用了它,但是您确切地做了什么?

请参阅此帖子获取更多详细信息:使用angular.js的CORS


如果您正在使用Wildfly(JBOSS 8.X),我编写了一个简单的Java类CorsFilter,它会向Web服务的响应添加一些CORS头。示例链接位于https://dev59.com/RmAg5IYBdhLWcg3wpMWz#23434583页面底部。 - javaauthority
1
你的个人博客链接似乎出现了问题。 - mlhDev

2
如果您想要使用数据POST到WebApi,那么您需要为Chrome做更多的工作。您需要拦截预检请求并将客户端来源包括在允许的来源中。
如果有更好的解决方案,那么在专门解决此问题的多天后,我找不到更好的解决方案。最终,这是对我有效的方法。
祝你好运...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Routing;

namespace MashupCoreApiApi
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }


        protected void Application_BeginRequest(object sender, EventArgs e)
        {

            if (Context.Request.Path.Contains("api/") && Context.Request.HttpMethod == "OPTIONS")
            {

                Context.Response.AddHeader("Access-Control-Allow-Origin", Context.Request.Headers["Origin"]);
                Context.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
                Context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST PUT, DELETE, OPTIONS");
                Context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                Context.Response.End();
            }

        } 

    }
}

0
如果你需要使用ASP.NET WebAPI,你需要安装CORS包并在Web服务器的启动中初始化CORS。
这个包叫做Microsoft.OWin.Cors。
在WebiApiConfig.cs中加入类似以下的内容:
var cors = new EnabledCorsAttribute("*", "*", "DataServiceVersion, MaxDataServiceVersion");
config.EnableCors(cors);

0

您需要稍微修改您的Web API以处理跨域请求。在Web Api项目中包含Microsoft Asp-Net Server Cors库和一些代码级别的修改,然后您就可以开始了。更多信息请查看这里

您的Angular部分完全没有问题。


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