如何在 AngularJs 中启用 CORS

我使用 JavaScript 为 Flickr 照片搜索 API 创建了一个演示。 现在我把它转换成 AngularJ。 我在互联网上搜索,发现以下配置。

配置:

myApp.config(function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});

服务范围:

myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.flickrPhotoSearch = function() {
return $http({
method: 'GET',
url: 'http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=3f807259749363aaa29c76012fa93945&tags=india&format=json&callback=?',
dataType: 'jsonp',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});

总监:

myApp.controller('flickrController', function($scope, dataService) {
$scope.data = null;
dataService.flickrPhotoSearch().then(function(dataResponse) {
$scope.data = dataResponse;
console.log($scope.data);
});
});

但我还是得到了同样的错误。 以下是我尝试过的一些链接:

XMLHttpRequest 无法加载 URL。访问控制-允许-起源不允许

Http://goo.gl/jus5b1

430448 次浏览

你不知道。您发出请求的服务器必须实现 CORS 才能从您的网站访问中授予 JavaScript。您的 JavaScript 不能授予自己访问其他网站的权限。

尝试使用资源服务来使用 flickr jsonp:

var MyApp = angular.module('MyApp', ['ng', 'ngResource']);


MyApp.factory('flickrPhotos', function ($resource) {
return $resource('http://api.flickr.com/services/feeds/photos_public.gne', { format: 'json', jsoncallback: 'JSON_CALLBACK' }, { 'load': { 'method': 'JSONP' } });
});


MyApp.directive('masonry', function ($parse) {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.masonry({ itemSelector: '.masonry-item', columnWidth: $parse(attrs.masonry)(scope) });
}
};
});


MyApp.directive('masonryItem', function () {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.imagesLoaded(function () {
elem.parents('.masonry').masonry('reload');
});
}
};
});


MyApp.controller('MasonryCtrl', function ($scope, flickrPhotos) {
$scope.photos = flickrPhotos.load({ tags: 'dogs' });
});

模板:

<div class="masonry: 240;" ng-controller="MasonryCtrl">
<div class="masonry-item" ng-repeat="item in photos.items">
<img ng-src="\{\{ item.media.m }}" />
</div>
</div>

我也遇到过类似的问题,对我来说,这可以归结为在 接收端回应处添加以下 HTTP 头:

Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *

您可能不希望在最后使用 *,而是仅使用发送数据的主机的域名。就像 *.example.com

但是,只有当您能够访问服务器的配置时,这才是可行的。

我自己回答。

CORS 角 js + restEasy on POST

最后我想到了一个解决办法: 它之所以能与 IE 一起工作,是因为 IE 直接发送一个 POST,而不是首先发送一个飞行前请求来获得许可。 但是我仍然不知道为什么过滤器不能管理一个 OPTION 请求,并且通过过滤器中没有描述的默认头发送(似乎只有在这种情况下才会重写... ... 也许是 restEasy 的事情... ...)

因此,我在我的休息服务中创建了一个 OPTION 路径,该路径重写响应,并使用响应头将响应头包含在响应中

如果以前有人遇到过这种情况,我仍然在寻找干净利落的方法。

        var result=[];
var app = angular.module('app', []);
app.controller('myCtrl', function ($scope, $http) {
var url="";// your request url
var request={};// your request parameters
var headers = {
// 'Authorization': 'Basic ' + btoa(username + ":" + password),
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json; charset=utf-8',
"X-Requested-With": "XMLHttpRequest"
}
$http.post(url, request, {
headers
})
.then(function Success(response) {
result.push(response.data);
$scope.Data = result;
},
function Error(response) {
result.push(response.data);
$scope.Data = result;
console.log(response.statusText + " " + response.status)
});
});


And also add following code in your WebApiConfig file
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);

这个问题的出现是由于网络应用安全模型的政策,即 同一原产地政策根据该政策,网络浏览器允许脚本包含在第一个网页访问数据在第二个网页,但只有当两个网页有相同的来源。这意味着请求者必须与请求站点的主机、协议和端口完全匹配。

我们有多种选择来克服这个 CORS 头问题。

  1. 使用 Proxy -在这个解决方案中,我们将运行一个代理,这样当请求通过代理时,它看起来就像是某个相同的起源。 如果你使用的是 NodeJS,你可以使用 任何地方来做代理的东西。

    示例 :-

    var host = process.env.HOST || '0.0.0.0';
    var port = process.env.PORT || 8080;
    var cors_proxy = require('cors-anywhere');
    cors_proxy.createServer({
    originWhitelist: [], // Allow all origins
    requireHeader: ['origin', 'x-requested-with'],
    removeHeaders: ['cookie', 'cookie2']
    }).listen(port, host, function() {
    console.log('Running CORS Anywhere on ' + host + ':' + port);
    });
    
  2. JSONP - JSONP is a method for sending JSON data without worrying about cross-domain issues.It does not use the XMLHttpRequest object.It uses the <script> tag instead. https://www.w3schools.com/js/js_json_jsonp.asp

  3. Server Side - On server side we need to enable cross-origin requests. First we will get the Preflighted requests (OPTIONS) and we need to allow the request that is status code 200 (ok).

    Preflighted requests first send an HTTP OPTIONS request header to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if it uses methods other than GET or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted. It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

    If you are using the spring just adding the bellow code will resolves the issue. Here I have disabled the csrf token that doesn't matter enable/disable according to your requirement.

    @SpringBootApplication
    public class SupplierServicesApplication {
    
    
    public static void main(String[] args) {
    SpringApplication.run(SupplierServicesApplication.class, args);
    }
    
    
    @Bean
    public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**").allowedOrigins("*");
    }
    };
    }
    }
    

    如果您正在使用弹簧安全性,请使用下面的代码和上面的代码。

    @Configuration
    @EnableWebSecurity
    public class SupplierSecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().antMatchers("/**").authenticated().and()
    .httpBasic();
    }
    
    
    }
    

我们可以使用 ngResourse 模块在前端启用 CORS。 但最重要的是,我们应该有这段代码,而使 Ajax 控制器中的请求,

$scope.weatherAPI = $resource(YOUR API,
{callback: "JSON_CALLBACK"}, {get: {method: 'JSONP'}});
$scope.weatherResult = $scope.weatherAPI.get(YOUR REQUEST DATA, if any);

另外,必须在脚本部分中添加 ngResourceCDN,并作为依赖项添加 在应用程序模块中。

<script src="https://code.angularjs.org/1.2.16/angular-resource.js"></script>

然后在 app 模块依赖项部分使用“ ngResourse”

var routerApp = angular.module("routerApp", ["ui.router", 'ngResource']);

Apache/HTTPD 在大多数企业中都存在,如果您在家中使用 Centos/etc 的话。因此,如果您有这样的服务器,那么可以非常容易地通过代理添加必要的 CORS 头。

我有一个关于这个 给你的博客文章,因为我最近受到它相当多的时间。但是重要的一点是将它添加到您的/etc/httpd/conf/httpd.conf 文件中,并确保您已经在执行“ List80”:

<VirtualHost *:80>
<LocationMatch "/SomePath">
ProxyPass http://target-ip:8080/SomePath
Header add "Access-Control-Allow-Origin" "*"
</LocationMatch>
</VirtualHost>

这样可以确保所有对 URL 的请求都通过 your-server-ip: 80/somPath 路由到 http://target-ip:8080/SomePath(不支持 CORS 的 API) ,并且返回正确的 Access-Control-allow-Origin 头以允许它们与 web-app 一起工作。

当然,如果愿意的话,您可以更改端口并将整个服务器作为目标,而不是选择 Some Path。

我遇到过类似的问题,问题出在后端。我正在使用节点服务器(Express)。我有一个前端(角度)如下所示的获取请求

   onGetUser(){
return this.http.get("http://localhost:3000/user").pipe(map(
(response:Response)=>{
const user =response.json();
return user;
}
))
}

但它出现了以下错误The error

这是使用 Express 编写的没有头部的后端代码

app.get('/user',async(req,res)=>{
const user=await getuser();
res.send(user);
})

在方法中增加一个报头后,问题得到了解决

app.get('/user',async(req,res)=>{
res.header("Access-Control-Allow-Origin", "*");
const user=await getuser();
res.send(user);
})

你可以得到更多关于 在 Node JS 上启用 CORS的细节

这个答案概述了解决不支持 CORS 的 API 的两种方法:

  • 使用 CORS 代理
  • 如果 API 支持,则使用 JSONP

一种变通方法是使用 CORS 代理:

angular.module("app",[])
.run(function($rootScope,$http) {
var proxy = "//cors-anywhere.herokuapp.com";
var url = "http://api.ipify.org/?format=json";
$http.get(proxy +'/'+ url)
.then(function(response) {
$rootScope.response = response.data;
}).catch(function(response) {
$rootScope.response = 'ERROR: ' + response.status;
})
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
Response = \{\{response}}
</body>

有关更多信息,请参见


如果 API 支持,则使用 JSONP:

 var url = "//api.ipify.org/";
var trust = $sce.trustAsResourceUrl(url);
$http.jsonp(trust,{params: {format:'jsonp'}})
.then(function(response) {
console.log(response);
$scope.response = response.data;
}).catch(function(response) {
console.log(response);
$scope.response = 'ERROR: ' + response.status;
})

关于 PLNKR 的演示

有关更多信息,请参见