我使用Flickr照片搜索API的JavaScript创建了一个演示。现在,我将其转换为AngularJs。我在互联网上搜索,发现下面的配置。
组态:
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);
});
});
但是我仍然遇到同样的错误。这是我尝试过的一些链接:
你不知道 您所请求的服务器必须实现CORS才能从您的网站访问权限中授予JavaScript。您的JavaScript无法授予自己访问另一个网站的权限。
我有一个类似的问题,对我来说,归结为在接收端的响应中添加以下HTTP标头:
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
您可能不希望*
在末尾使用,而仅使用发送数据的主机的域名。喜欢*.example.com
但这仅在您有权访问服务器的配置时才可行。
尝试使用资源服务来消耗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>
发生此问题的原因是,Web应用程序安全模型策略是“相同来源策略”。根据该策略,Web浏览器允许第一个网页中包含的脚本访问第二个网页中的数据,但前提是两个网页的来源相同。这意味着请求者必须匹配请求站点的确切主机,协议和端口。
我们有多种选择可以解决这个CORS标头问题。
-
使用代理-在此解决方案中,我们将运行代理,以便当请求通过代理时,它看起来就像是某个相同的来源。如果您使用的是nodeJS,则可以在任何地方使用cors-做代理工作。https://www.npmjs.com/package/cors-anywhere。
例子:-
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); });
-
JSONP -JSONP是一种发送JSON数据而无需担心跨域问题的方法,它不使用XMLHttpRequest对象,
<script>
而是使用标记。https://www.w3schools.com/js/js_json_jsonp.asp -
服务器端-在服务器端,我们需要启用跨域请求。首先,我们将获得预检请求(OPTIONS),我们需要允许状态代码为200的请求(确定)。
预检请求首先将HTTP OPTIONS请求标头发送到另一个域上的资源,以确定实际请求是否可以安全发送。跨站点请求这样被预检,因为它们可能会影响用户数据。特别是,如果请求使用GET或POST以外的方法,则该请求将被预检。另外,如果POST用于发送请求类型为application / x-www-form-urlencoded,multipart / form-data或text / plain之外的Content-Type的请求数据,例如POST请求将XML有效负载发送给服务器使用application / xml或text / xml,则对请求进行预检。它在请求中设置自定义标头(例如,请求使用标头,例如X-PINGOTHER)
如果您使用的是弹簧,只需添加以下代码即可解决该问题。在这里,我已禁用了csrf令牌,这与根据您的要求启用/禁用无关。
@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("*"); } }; } }
如果您使用的是Spring Security,请同时使用以下代码和上述代码。
@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(); } }
我遇到了类似的问题,后端存在问题。我正在使用节点服务器(快速)。我有一个从前端(角度)的获取请求,如下所示
onGetUser(){
return this.http.get("http://localhost:3000/user").pipe(map(
(response:Response)=>{
const user =response.json();
return user;
}
))
}
这是使用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的更多详细信息。
我自己回答。
POST上的CORS angular js + restEasy
好吧,最后我来到了这种解决方法:它与IE一起使用的原因是因为IE直接发送POST而不是首先发送预检请求以请求许可。但是我仍然不知道为什么过滤器无法管理OPTIONS请求并默认发送过滤器中未描述的标头(似乎仅在这种情况下是覆盖...也许是restEasy的事情.. )
因此,我在我的rest服务中创建了一个OPTIONS路径,该路径重写了响应并使用响应标头将标头包含在响应中
如果有人以前遇到过这种情况,我仍在寻找一种干净的方法。
在大多数企业中,或者您在家中使用Centos / etc时,Apache / HTTPD往往都存在。因此,如果有这种情况,您可以非常轻松地执行代理以添加必要的CORS标头。
我在这里有一篇博客文章,因为最近我遭受了很多次。但是重要的一点只是将其添加到/etc/httpd/conf/httpd.conf文件中,并确保您已经在执行“ Listen 80”:
<VirtualHost *:80>
<LocationMatch "/SomePath">
ProxyPass http://target-ip:8080/SomePath
Header add "Access-Control-Allow-Origin" "*"
</LocationMatch>
</VirtualHost>
这样可以确保所有对your-server-ip:80 / SomePath下的URL的请求都路由到http:// target-ip:8080 / SomePath(不具有CORS支持的API),并确保它们返回正确的Access-Control-Allow- Origin标头,使他们可以与您的网络应用一起使用。
当然,您可以根据需要更改端口并以整个服务器为目标,而不是SomePath。
此答案概述了解决不支持CORS的API的两种方法:
- 使用CORS代理
- 如果API支持,请使用JSONP
一种解决方法是使用CORS PROXY:
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;
})
有关更多信息,请参见
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);
我们可以使用ngResourse模块在前端启用CORS。但最重要的是,在控制器中发出ajax请求时,我们应该拥有这段代码,
$scope.weatherAPI = $resource(YOUR API,
{callback: "JSON_CALLBACK"}, {get: {method: 'JSONP'}});
$scope.weatherResult = $scope.weatherAPI.get(YOUR REQUEST DATA, if any);
另外,您必须在脚本部分中添加ngResourse CDN,并在应用程序模块中将其添加为依赖项。
<script src="https://code.angularjs.org/1.2.16/angular-resource.js"></script>
然后在应用模块依赖项部分中使用“ ngResourse”
var routerApp = angular.module("routerApp", ["ui.router", 'ngResource']);
文章标签:angularjs , cors , javascript , xmlhttprequest
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!