Javascript 如何在AngularJs中启用CORS

Javascript 如何在AngularJs中启用CORS,javascript,angularjs,xmlhttprequest,cors,Javascript,Angularjs,Xmlhttprequest,Cors,我已经使用JavaScript为Flickr照片搜索API创建了一个演示。 现在我把它转换成AngularJs。 我在网上搜索了一下,找到了下面的配置 配置: myApp.config(function($httpProvider) { $httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers.common['X-Requested-With']; }); 服务: myApp.serv

我已经使用JavaScript为Flickr照片搜索API创建了一个演示。 现在我把它转换成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无法授予自己访问其他网站的权限。

请尝试使用资源服务来使用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

但这只有在您可以访问服务器的配置时才可行。

我自己回答

最后我想到了这个解决办法: 它与IE一起工作的原因是,IE直接发送一个POST,而不是首先发送一个飞行前请求以请求许可。 但是我仍然不知道为什么过滤器不能管理选项请求,并且默认发送过滤器中没有描述的头文件(似乎只是在这种情况下进行了覆盖…可能是一件容易的事情…)

因此,我在我的rest服务中创建了一个选项路径,该路径重写响应,并使用响应头在响应中包含头


如果以前有人遇到过这个问题,我仍然在寻找一种干净的方法来解决这个问题。

出现这个问题是因为web应用程序安全模型策略是同源策略。在该策略下,web浏览器允许第一个网页中包含的脚本访问第二个网页中的数据,但前提是两个网页的来源相同。这意味着请求者必须匹配请求站点的确切主机、协议和端口

        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标题问题

  • 使用代理-在这个解决方案中,我们将运行一个代理,这样当请求通过代理时,它将看起来像是某个相同的来源。 如果您使用的是节点js,则可以使用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对象。它使用
    标记

  • 服务器端-在服务器端,我们需要启用跨源请求。 首先,我们将获得预飞行请求(选项),我们需要允许状态代码为200的请求(确定)

    预引导请求首先向另一个域上的资源发送HTTP OPTIONS请求头,以确定发送实际请求是否安全。跨站点请求是这样预处理的,因为它们可能会影响用户数据。特别是,如果请求使用GET或POST以外的方法,则请求将被预引导。此外,如果POST用于发送内容类型不是application/x-www-form-urlencoded、multipart/form data或text/plain的请求数据,例如,如果POST请求使用application/XML或text/XML向服务器发送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();
        }
    
    }
    

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

    $scope.weatherAPI = $resource(YOUR API,
         {callback: "JSON_CALLBACK"}, {get: {method: 'JSONP'}});
     $scope.weatherResult = $scope.weatherAPI.get(YOUR REQUEST DATA, if any);
    
    此外,您必须在脚本部分中添加NGResources CDN,并作为依赖项添加 在应用程序模块中

    <script src="https://code.angularjs.org/1.2.16/angular-resource.js"></script>
    
    
    
    然后在应用程序模块依赖项部分使用“ngresource”


    var routerApp=angular.module(“routerApp”、“ui.router”、“ngResource”)

    Apache/HTTPD通常出现在大多数企业中,或者如果您在家中使用Centos/etc。因此,如果你有这样的想法,你可以很容易地做一个代理来添加必要的CORS头

    我有一篇关于这件事的博客文章,因为我最近有好几次因为它而痛苦。但重要的是将其添加到/etc/httpd/conf/httpd.conf文件中,并确保您已经在执行“Listen 80”:

    
    ProxyPasshttp://target-ip:8080/SomePath
    标题添加“访问控制允许来源”“*”
    
    这可以确保对服务器ip:80/SomePath下URL的所有请求都会路由到(不支持CORS的API),并且它们返回时具有正确的访问控制Allow Origin标头,以允许它们使用您的web应用程序


    当然,如果您愿意,您可以更改端口并针对整个服务器,而不是某个路径。

    我遇到了类似的问题,问题是后端。我使用的是节点服务器(Express)。我收到了来自前端(angular)的get请求,如下所示

       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);
    })
    

    您可以获得有关

    的更多详细信息此答案概述了两种解决不支持CORS的API的方法:

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

    一种解决方法是使用CORS代理:

    角度模块(“应用程序”,[]) .run(函数($rootScope,$http){ var proxy=“//cors anywhere.herokuapp.com”; 瓦尔乌尔
    app.get('/user',async(req,res)=>{
        res.header("Access-Control-Allow-Origin", "*");
        const user=await getuser();
        res.send(user);
    })