如何在AngularJs中启用CORS

时间:2022-08-22 17:46:15

I have created a demo using JavaScript for Flickr photo search API. Now I am converting it to the AngularJs. I have searched on internet and found below configuration.

我使用JavaScript为Flickr照片搜索API创建了一个演示。现在我把它转换成盎格鲁人。我在互联网上搜索过,在配置下面。

Configuration:

配置:

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

Service:

服务:

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

Controller:

控制器:

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

But still I got the same error. Here are some links I tried:

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

XMLHttpRequest cannot load URL. Origin not allowed by Access-Control-Allow-Origin

XMLHttpRequest不能加载URL。访问控制允许的原点不允许

http://samurails.com/tutorial/cors-with-angular-js-and-sinatra/

http://samurails.com/tutorial/cors-with-angular-js-and-sinatra/

EDIT:

编辑:

I created a proxy server in node.js on suggestion of @Quentin:

我在node中创建了一个代理服务器。关于@Quentin的建议:

var http = require('http');
var url = require('url');
var fs = require('fs');
var server;

server = http.createServer(function (req, res) {
    // your normal server code
    var path = url.parse(req.url).pathname;
    fs.readFile(__dirname + path, function (err, data) {
        if (err) {
            return send404(res);
        }
        res.writeHead(200, {'Content-Type':path == 'json.js' ? 'text/javascript' : 'text/html'});
        res.write(data, 'utf8');
        res.end();
    });
}),
server.listen(8001);
//using express to load customizes static files
var express = require("express"),
    app = express();

app.all("/api/*", function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
    res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
    return next();
});
app.use("/js", express.static(__dirname + '/js'));
app.listen(3001);

Final Edit

最后编辑

I removed the Authorization header

我删除了授权头

headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}

标题:{“授权”:“令牌令牌= xxxxYYYYZzzz ' }

and it is running alright. I have got what I wanted. Thanks everyone for participation in this question

它运行正常。我得到了我想要的。谢谢大家参与这个问题

6 个解决方案

#1


163  

You don't. The server you are making the request to has to implement CORS to grant JavaScript from your website access. Your JavaScript can't grant itself permission to access another website.

你不。您所请求的服务器必须实现CORS以从您的网站访问中授予JavaScript。你的JavaScript不能允许自己访问另一个网站。

#2


56  

I had a similar problem and for me it boiled down to adding the following HTTP headers at the response of the receiving end:

我遇到了类似的问题,对我来说,可以归结为在接收端响应时添加以下HTTP报头:

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

You may prefer not to use the * at the end, but only the domainname of the host sending the data. Like *.example.com

您可能不希望在最后使用*,但是只使用主机发送数据的domainname。像.example.com *

But this is only feasible when you have access to the configuration of the server.

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

#3


9  

Try using the resource service to consume flickr jsonp:

尝试使用资源服务来使用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' });
});

Template:

模板:

<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>

#4


1  

Answered by myself.

自己回答。

CORS angular js + restEasy on POST

有角的js +哨岗的restEasy

Well finally I came to this workaround: The reason it worked with IE is because IE sends directly a POST instead of first a preflight request to ask for permission. But I still don't know why the filter wasn't able to manage an OPTIONS request and sends by default headers that aren't described in the filter (seems like an override for that only case ... maybe a restEasy thing ...)

最后我找到了解决方案:它与IE合作的原因是IE直接发送一个POST,而不是先发送一个飞行前请求来请求许可。但是,我仍然不知道为什么过滤器不能管理一个选项请求,并发送默认的头文件,而这些头文件在过滤器中没有被描述。也许是一件让人讨厌的事……

So I created an OPTIONS path in my rest service that rewrites the reponse and includes the headers in the response using response header

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

I'm still looking for the clean way to do it if anybody faced this before.

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

#5


1  

This issue occurs because of web application security model policy that is Same Origin Policy Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. That means requester must match the exact host, protocol, and port of requesting site.

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

We have multiple options to over come this CORS header issue.

我们有多个选项来解决CORS头问题。

  1. Using Proxy - In this solution we will run a proxy such that when request goes through the proxy it will appear like it is some same origin. If you are using the nodeJS you can use cors-anywhere to do the proxy stuff. https://www.npmjs.com/package/cors-anywhere.

    使用代理——在这个解决方案中,我们将运行一个代理,当请求通过代理时,它将显示为相同的源。如果您使用的是nodeJS,您可以使用cors—在任何地方做代理。https://www.npmjs.com/package/cors-anywhere。

    Example:-

    例子:-

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

    主机= process.env var。主机| |“0.0.0.0”;var = process.env港。港| | 8080;var cors_proxy =要求(“cors-anywhere”);cors_proxy。createServer({whitelist:[], //允许所有起源请求:['origin', 'x-requested-with'], removeheader: ['cookie', 'cookie2']})。监听(端口,主机,函数()控制台。日志('在' + host + ':' +端口上运行CORS);});

  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

    JSONP - JSONP是一种发送JSON数据而无需担心跨域问题的方法。它不使用XMLHttpRequest对象。它使用

  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).

    服务器端-在服务器端,我们需要启用跨源请求。首先,我们将获得预置请求(选项),我们需要允许的请求是状态码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)

    预置请求首先向其他域的资源发送一个HTTP选项请求头,以确定实际请求是否安全发送。跨站点请求是这样的,因为它们可能对用户数据有影响。特别是,如果一个请求使用的方法不是GET或POST,那么它就是级联的。另外,如果POST用于发送除application/ www-form- urlencodes、multipart/form-data或text/plain之外的内容类型的请求数据,例如,如果POST请求使用application/ XML或text/ XML向服务器发送XML有效负载,那么该请求是预先完成的。它在请求中设置自定义头(例如,请求使用一个头,如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.

    如果您正在使用spring,只需添加下面的代码就可以解决这个问题。在这里,我已经禁用了csrf令牌,这与根据您的要求启用/禁用无关。

    @SpringBootApplication public class SupplierServicesApplication {

    @ springbootapplicationpublic类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("*");
            }
        };
    }
    

    }

    }

    If you are using the spring security use below code along with above code.

    如果您正在使用下面的代码和上面的代码的spring安全使用。

    @Configuration @EnableWebSecurity public class SupplierSecurityConfig extends WebSecurityConfigurerAdapter {

    @Configuration @EnableWebSecurity公共类SupplierSecurityConfig扩展了WebSecurityConfigurerAdapter {

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

    }

    }

#6


-1  

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

#1


163  

You don't. The server you are making the request to has to implement CORS to grant JavaScript from your website access. Your JavaScript can't grant itself permission to access another website.

你不。您所请求的服务器必须实现CORS以从您的网站访问中授予JavaScript。你的JavaScript不能允许自己访问另一个网站。

#2


56  

I had a similar problem and for me it boiled down to adding the following HTTP headers at the response of the receiving end:

我遇到了类似的问题,对我来说,可以归结为在接收端响应时添加以下HTTP报头:

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

You may prefer not to use the * at the end, but only the domainname of the host sending the data. Like *.example.com

您可能不希望在最后使用*,但是只使用主机发送数据的domainname。像.example.com *

But this is only feasible when you have access to the configuration of the server.

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

#3


9  

Try using the resource service to consume flickr jsonp:

尝试使用资源服务来使用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' });
});

Template:

模板:

<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>

#4


1  

Answered by myself.

自己回答。

CORS angular js + restEasy on POST

有角的js +哨岗的restEasy

Well finally I came to this workaround: The reason it worked with IE is because IE sends directly a POST instead of first a preflight request to ask for permission. But I still don't know why the filter wasn't able to manage an OPTIONS request and sends by default headers that aren't described in the filter (seems like an override for that only case ... maybe a restEasy thing ...)

最后我找到了解决方案:它与IE合作的原因是IE直接发送一个POST,而不是先发送一个飞行前请求来请求许可。但是,我仍然不知道为什么过滤器不能管理一个选项请求,并发送默认的头文件,而这些头文件在过滤器中没有被描述。也许是一件让人讨厌的事……

So I created an OPTIONS path in my rest service that rewrites the reponse and includes the headers in the response using response header

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

I'm still looking for the clean way to do it if anybody faced this before.

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

#5


1  

This issue occurs because of web application security model policy that is Same Origin Policy Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. That means requester must match the exact host, protocol, and port of requesting site.

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

We have multiple options to over come this CORS header issue.

我们有多个选项来解决CORS头问题。

  1. Using Proxy - In this solution we will run a proxy such that when request goes through the proxy it will appear like it is some same origin. If you are using the nodeJS you can use cors-anywhere to do the proxy stuff. https://www.npmjs.com/package/cors-anywhere.

    使用代理——在这个解决方案中,我们将运行一个代理,当请求通过代理时,它将显示为相同的源。如果您使用的是nodeJS,您可以使用cors—在任何地方做代理。https://www.npmjs.com/package/cors-anywhere。

    Example:-

    例子:-

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

    主机= process.env var。主机| |“0.0.0.0”;var = process.env港。港| | 8080;var cors_proxy =要求(“cors-anywhere”);cors_proxy。createServer({whitelist:[], //允许所有起源请求:['origin', 'x-requested-with'], removeheader: ['cookie', 'cookie2']})。监听(端口,主机,函数()控制台。日志('在' + host + ':' +端口上运行CORS);});

  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

    JSONP - JSONP是一种发送JSON数据而无需担心跨域问题的方法。它不使用XMLHttpRequest对象。它使用

  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).

    服务器端-在服务器端,我们需要启用跨源请求。首先,我们将获得预置请求(选项),我们需要允许的请求是状态码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)

    预置请求首先向其他域的资源发送一个HTTP选项请求头,以确定实际请求是否安全发送。跨站点请求是这样的,因为它们可能对用户数据有影响。特别是,如果一个请求使用的方法不是GET或POST,那么它就是级联的。另外,如果POST用于发送除application/ www-form- urlencodes、multipart/form-data或text/plain之外的内容类型的请求数据,例如,如果POST请求使用application/ XML或text/ XML向服务器发送XML有效负载,那么该请求是预先完成的。它在请求中设置自定义头(例如,请求使用一个头,如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.

    如果您正在使用spring,只需添加下面的代码就可以解决这个问题。在这里,我已经禁用了csrf令牌,这与根据您的要求启用/禁用无关。

    @SpringBootApplication public class SupplierServicesApplication {

    @ springbootapplicationpublic类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("*");
            }
        };
    }
    

    }

    }

    If you are using the spring security use below code along with above code.

    如果您正在使用下面的代码和上面的代码的spring安全使用。

    @Configuration @EnableWebSecurity public class SupplierSecurityConfig extends WebSecurityConfigurerAdapter {

    @Configuration @EnableWebSecurity公共类SupplierSecurityConfig扩展了WebSecurityConfigurerAdapter {

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

    }

    }

#6


-1  

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