So aktivieren Sie CORS in AngularJs

147

Ich habe eine Demo mit JavaScript für die Flickr-Fotosuch-API erstellt. Jetzt konvertiere ich es in die AngularJs. Ich habe im Internet gesucht und unten Konfiguration gefunden.

Aufbau:

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

Bedienung:

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

Regler:

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

Trotzdem habe ich den gleichen Fehler bekommen. Hier sind einige Links, die ich ausprobiert habe:

XMLHttpRequest kann keine URL laden. Ursprung von Access-Control-Allow-Origin nicht erlaubt

http://goo.gl/JuS5B1

ankitr
quelle
1
Sie müssen die Daten von Ihrem Proxy anfordern, Sie fordern sie weiterhin direkt von flickr an.
Quentin
@quentin Danke für die schnelle Antwort. Können Sie mir bitte eine Demo geben?
Ankitr
1
Sie ändern einfach die URL von flickr.com in die URL Ihres Proxys
Quentin
1
Aber wie soll ich flickr nennen? da brauche ich die bilder von flickr.
Ankitr
2
Der Client ruft den Proxy an. Der Proxy ruft flickr auf. Das bedeutet Proxy. (Ihr Proxy-Code… ist kein Proxy, sondern ein Webserver zum Bereitstellen von JSON und JSONP aus statischen Dateien.)
Quentin

Antworten:

193

Das tust du nicht. Der Server, an den Sie die Anfrage stellen, muss CORS implementieren, um JavaScript von Ihrem Website-Zugriff aus zu gewähren. Ihr JavaScript kann sich keine Berechtigung zum Zugriff auf eine andere Website erteilen.

QUentin
quelle
1
Stellen Sie die Anforderungen stattdessen von Ihrem Server an Flickr.
Quentin
Ich benutze keinen Server, aber ich kann node.js verwenden. Können Sie mir damit den Weg zeigen?
Ankitr
1
Nicht in dem in einem Kommentar verfügbaren Bereich. Es ist eher eine große Reihe von Themen.
Quentin
Warum ist es , dass ich eine Antwort von bekommen kann https://www.google.commit einer Anwendung wie POSTMAN, aber wenn ich versuche, GETaus https://www.google.commit einem AJAX - Aufruf ich die CORS Fehlermeldung erhalten? Kann ich den AJAX-Anruf auf keinen Fall ähnlich wie den Anruf von POSTMAN verhalten?
AjaxLeung
5
@AlexLeung - Postman ist eine installierte Anwendung. Wenn Ihre Website meinen Browser dazu bringen könnte, Daten von Google anzufordern und zu lesen, könnte Ihre Website meine GMail-Posteingangsseite anfordern und alle meine E-Mails lesen. Das wäre schrecklich.
Quentin
64

Ich hatte ein ähnliches Problem und für mich lief es darauf hinaus, die folgenden HTTP-Header bei der Antwort des empfangenden Endes hinzuzufügen :

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

Möglicherweise möchten Sie das *am Ende nicht verwenden, sondern nur den Domänennamen des Hosts, der die Daten sendet. Mögen*.example.com

Dies ist jedoch nur möglich, wenn Sie Zugriff auf die Konfiguration des Servers haben.

Erwin
quelle
2
Ich bin neu in AngularJs. Können Sie mir bitte sagen, wo ich das implementieren soll?
Ankitr
17
@Ankit Sie müssen diese Header auf dem Server hinzufügen , nicht in AngularJS.
Felipe Almeida
2
@techcraver - Sie benötigen keinen operativen Zugriff auf die Konfiguration des Servers. Übergeben Sie einfach die Header aus Ihrem Skript. Wenn Sie ein PHP-Backend haben, wäre esheader('Access-Control-Allow-Origin: *');
Davidkonrad
@davidkonrad: Ich habe die ganze App in Angular V4 erstellt. Kannst du sagen, wo ich diese Überschrift
einfügen muss
@ Pygirl, ich glaube du hast die Kundenseite eckig gemacht? Sie müssen der Antwortserverseite Header hinzufügen, wie und wo dies von der Technologie abhängt. Wenn es sich um ein PHP-Skript handelt, das Sie aus einem Winkel Http.get()oder ähnlichem aufrufen , fügen Sie es header('Access-Control-Allow-Origin: *')als allererste Ausgabe in das aufgerufene PHP-Skript ein (dh bevor Sie die eigentliche Antwort JSON ausgeben, was auch immer.
davidkonrad
9

Verwenden Sie den Ressourcendienst, um flickr jsonp zu verwenden:

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

Vorlage:

<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>
Ali Habibzadeh
quelle
4

Dieses Problem tritt auf, weil der Web Application Security Modellpolitik , die ist Same Origin Policy Im Rahmen der Politik, einen Web - Browser ermöglicht Skripte in einer ersten Web - Seite den Zugriff auf Daten in einer zweiten Web - Seite enthalten ist , aber nur , wenn beide Seiten den gleichen Ursprung haben . Dies bedeutet, dass der Anforderer mit dem genauen Host, Protokoll und Port des anfordernden Standorts übereinstimmen muss.

Wir haben mehrere Möglichkeiten, um dieses CORS-Header-Problem zu lösen.

  1. Verwenden von Proxy - In dieser Lösung führen wir einen Proxy so aus, dass die Anfrage, wenn sie über den Proxy gesendet wird, so aussieht, als ob sie denselben Ursprung hat. Wenn Sie den NodeJS verwenden , können Sie Cors -Anywhere verwenden , um die Proxy- Aufgaben zu erledigen. https://www.npmjs.com/package/cors-anywhere .

    Beispiel : -

    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 ist eine Methode zum Senden von JSON-Daten, ohne sich um domänenübergreifende Probleme kümmern zu müssen. Das XMLHttpRequest-Objekt wird nicht verwendet. Stattdessen wird das <script>Tag verwendet. https://www.w3schools.com/js/js_json_jsonp.asp

  3. Serverseite - Auf der Serverseite müssen wir Cross-Origin-Anforderungen aktivieren. Zuerst erhalten wir die Preflighted-Anfragen (OPTIONEN) und müssen die Anfrage mit dem Statuscode 200 (ok) zulassen .

    Preflight-Anforderungen senden zuerst einen HTTP OPTIONS-Anforderungsheader an die Ressource in der anderen Domäne, um festzustellen, ob die tatsächliche Anforderung sicher zu senden ist. Standortübergreifende Anforderungen werden auf diese Weise vorab ausgeführt, da sie Auswirkungen auf Benutzerdaten haben können. Insbesondere wird eine Anforderung vorab ausgeführt, wenn andere Methoden als GET oder POST verwendet werden. Wenn POST zum Senden von Anforderungsdaten mit einem anderen Inhaltstyp als application / x-www-form-urlencoded, multipart / form-data oder text / plain verwendet wird, z. B. wenn die POST-Anforderung eine XML-Nutzlast an den Server sendet Wenn Sie application / xml oder text / xml verwenden, wird die Anforderung vorab ausgeführt. Es werden benutzerdefinierte Header in der Anforderung festgelegt (z. B. verwendet die Anforderung einen Header wie X-PINGOTHER).

    Wenn Sie die Feder verwenden, wird das Problem durch Hinzufügen des folgenden Codes behoben. Hier habe ich das csrf-Token deaktiviert, das unabhängig von Ihren Anforderungen keine Rolle spielt.

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

    Wenn Sie die Federsicherung verwenden, verwenden Sie den folgenden Code zusammen mit dem obigen Code.

    @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();
        }
    
    }
Niru
quelle
2

Ich bin auf ein ähnliches Problem wie dieses gestoßen, das Problem war das Backend. Ich habe Node Server (Express) verwendet. Ich hatte eine Get-Anfrage vom Frontend (eckig), wie unten gezeigt

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

Aber es gab den folgenden FehlerDer Fehler

Dies ist der Backend-Code, der mit Express ohne die Header geschrieben wurde

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

Nach dem Hinzufügen eines Headers zur Methode wurde das Problem gelöst

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

Weitere Informationen zum Aktivieren von CORS auf Node JS erhalten Sie

Janith Udara
quelle
1

Von mir selbst beantwortet.

CORS eckig js + restEasy auf POST

Nun, endlich bin ich zu dieser Problemumgehung gekommen: Der Grund, warum es mit IE funktioniert hat, ist, dass IE direkt einen POST sendet, anstatt zuerst eine Preflight-Anfrage, um um Erlaubnis zu bitten. Aber ich weiß immer noch nicht, warum der Filter eine OPTIONS-Anforderung nicht verwalten konnte und standardmäßig Header sendet, die nicht im Filter beschrieben sind (scheint eine Überschreibung für diesen einzigen Fall zu sein ... vielleicht eine einfache Sache). .)

Daher habe ich in meinem Rest-Service einen OPTIONS-Pfad erstellt, der die Antwort neu schreibt und die Header mithilfe des Antwortheaders in die Antwort einbezieht

Ich bin immer noch auf der Suche nach einem sauberen Weg, wenn jemand dies zuvor gesehen hat.

J.Doe
quelle
1

Apache / HTTPD gibt es in den meisten Unternehmen oder wenn Sie Centos / etc zu Hause verwenden. Wenn Sie das haben, können Sie sehr einfach einen Proxy erstellen, um die erforderlichen CORS-Header hinzuzufügen.

Ich habe hier einen Blog-Beitrag dazu , da ich in letzter Zeit einige Male darunter gelitten habe. Das Wichtigste ist jedoch, dies einfach zu Ihrer Datei /etc/httpd/conf/httpd.conf hinzuzufügen und sicherzustellen, dass Sie bereits "Listen 80" ausführen:

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

Dadurch wird sichergestellt, dass alle Anforderungen an URLs unter Ihrer Server-IP: 80 / SomePath-Route an http: // Ziel-IP: 8080 / SomePath (die API ohne CORS-Unterstützung) weitergeleitet werden und mit der richtigen Zugriffssteuerung (Zulässig) zurückgegeben werden. Origin-Header, damit sie mit Ihrer Web-App arbeiten können.

Natürlich können Sie die Ports ändern und auf den gesamten Server anstatt auf SomePath abzielen, wenn Sie möchten.

John Humphreys - w00te
quelle
1

Diese Antwort beschreibt zwei Möglichkeiten, um APIs zu umgehen, die CORS nicht unterstützen:

  • Verwenden Sie einen CORS-Proxy
  • Verwenden Sie JSONP, wenn die API dies unterstützt

Eine Problemumgehung ist die Verwendung eines 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>

Weitere Informationen finden Sie unter


Verwenden Sie JSONP, wenn die API dies unterstützt:

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

Die DEMO auf PLNKR

Weitere Informationen finden Sie unter

georgeawg
quelle
0
        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);
Shiva Samalla
quelle
"Und fügen Sie außerdem folgenden Code in Ihre WebApiConfig-Datei ein" - Bei der Frage geht es darum, eine Anfrage an Flickr zu stellen. Ihre Server stehen nicht unter der Kontrolle des OP. Flickr verwendet wahrscheinlich auch kein ASP.NET.
Quentin
0

Wir können CORS im Frontend mithilfe des ngResourse-Moduls aktivieren. Am wichtigsten ist jedoch, dass wir diesen Code haben, während wir die Ajax-Anfrage im Controller stellen.

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

Außerdem müssen Sie ngResourse CDN im Skriptteil hinzufügen und als Abhängigkeit im App-Modul hinzufügen.

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

Verwenden Sie dann "ngResourse" im Abschnitt "Abhängigkeit des App-Moduls"

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

Alok Ranjan
quelle