Cara mengaktifkan CORS di AngularJs

147

Saya telah membuat demo menggunakan API pencarian foto Flickr untuk JavaScript. Sekarang saya mengubahnya menjadi AngularJs. Saya telah mencari di internet dan menemukan konfigurasi di bawah ini.

Konfigurasi:

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

Layanan:

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

Pengendali:

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

Tapi tetap saja saya mendapat kesalahan yang sama. Berikut ini beberapa tautan yang saya coba:

XMLHttpRequest tidak dapat memuat URL. Asal tidak diizinkan oleh Access-Control-Allow-Origin

http://goo.gl/JuS5B1

ankitr
sumber
1
Anda harus meminta data dari proxy Anda, Anda masih memintanya langsung dari flickr.
Quentin
@quentin Terima kasih atas balasan cepat. Tolong beri saya demo.
ankitr
1
Anda cukup mengubah URL dari flickr.com ke URL proxy Anda
Quentin
1
Tetapi bagaimana saya akan memanggil flickr? karena saya membutuhkan gambar dari flickr.
ankitr
2
Klien memanggil proxy. Proxy memanggil flickr. Itulah arti proxy. (Kode proxy Anda ... bukan proxy, ini adalah server web untuk melayani JSON dan JSONP dari file statis).
Quentin

Jawaban:

194

Kamu tidak. Server yang Anda minta harus menerapkan CORS untuk memberikan JavaScript dari akses situs web Anda. JavaScript Anda tidak dapat memberikan izin kepada dirinya sendiri untuk mengakses situs web lain.

Quentin
sumber
1
Sebaliknya, buat permintaan ke Flickr dari server Anda.
Quentin
Saya tidak menggunakan server tetapi saya bisa menggunakan node.js. Bisakah Anda menunjukkan kepada saya caranya dengan ini?
ankitr
1
Tidak ada ruang di komentar. Agak banyak topik.
Quentin
Mengapa saya bisa mendapatkan respon dari https://www.google.commenggunakan aplikasi seperti Postman, tetapi ketika saya mencoba untuk GETdari https://www.google.commenggunakan panggilan AJAX saya mendapatkan error CORS? Apakah saya tidak bisa membuat panggilan AJAX berperilaku serupa dengan panggilan dari POSTMAN?
AjaxLeung
6
@AlexLeung - Postman adalah aplikasi yang diinstal. Jika situs web Anda dapat membuat data permintaan browser saya dari Google dan membacanya, maka situs web Anda dapat meminta halaman Kotak Masuk GMail saya dan membaca semua email saya. Itu akan mengerikan.
Quentin
64

Saya punya masalah yang sama dan bagi saya itu bermuara pada menambahkan header HTTP berikut pada respon dari penerima :

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

Anda mungkin memilih untuk tidak menggunakan *di bagian akhir, tetapi hanya nama domain dari host yang mengirim data. Suka*.example.com

Tetapi ini hanya layak bila Anda memiliki akses ke konfigurasi server.

Erwin
sumber
2
Saya baru di AngularJs. Tolong bisakah Anda memberi tahu saya di mana harus menerapkan ini?
ankitr
18
@Ankit Anda harus menambahkan header ini di server , bukan di AngularJS.
Felipe
2
@ techcraver - Anda tidak memerlukan akses operasional ke konfigurasi server - cukup kirimkan header dari dalam skrip Anda. Jika Anda memiliki PHP backendheader('Access-Control-Allow-Origin: *');
davidkonrad
@davidkonrad: Saya telah membuat seluruh aplikasi dalam v4 sudut. Dapatkah Anda memberi tahu di mana saya harus memasukkan tajuk ini: /
Pygirl
@Pygirl, saya yakin Anda telah membuat sisi klien di sudut? Anda perlu menambahkan header di sisi server tanggapan, bagaimana dan di mana bergantung pada teknologi. Jika ini adalah skrip PHP yang Anda panggil dari sudut Http.get()atau sejenisnya, tambahkan header('Access-Control-Allow-Origin: *')sebagai output pertama dalam skrip PHP yang disebut (yaitu sebelum Anda menampilkan respons aktual, JSON, apa pun.
davidkonrad
9

Coba gunakan layanan sumber daya untuk mengkonsumsi 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' });
});

Templat:

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

Masalah ini terjadi karena kebijakan model keamanan aplikasi web yaitu Kebijakan Asal yang Sama Di bawah kebijakan tersebut, peramban web mengizinkan skrip yang terkandung dalam halaman web pertama untuk mengakses data di halaman web kedua, tetapi hanya jika kedua halaman web memiliki asal yang sama. Itu berarti pemohon harus cocok dengan host, protokol, dan port situs permintaan yang tepat.

Kami memiliki beberapa opsi untuk mengatasi masalah header CORS ini.

  1. Menggunakan Proxy - Dalam solusi ini kami akan menjalankan proxy sehingga ketika permintaan melewati proxy itu akan tampak seperti itu adalah asal yang sama. Jika Anda menggunakan nodeJS Anda dapat menggunakan cors-mana saja untuk melakukan hal-hal proxy. https://www.npmjs.com/package/cors-anywhere .

    Contoh : -

    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 adalah metode untuk mengirim data JSON tanpa khawatir tentang masalah lintas domain. Ini tidak menggunakan objek XMLHttpRequest. Ia menggunakan <script>tag sebagai gantinya. https://www.w3schools.com/js/js_json_jsonp.asp

  3. Sisi Server - Di sisi server kami harus mengaktifkan permintaan lintas-asal. Pertama kita akan mendapatkan permintaan Preflighted (OPTIONS) dan kita harus mengizinkan permintaan itu adalah kode status 200 (ok).

    Permintaan preflighted terlebih dahulu mengirim header permintaan HTTP OPTIONS ke sumber daya di domain lain, untuk menentukan apakah permintaan sebenarnya aman untuk dikirim. Permintaan lintas-situs lebih dulu seperti ini karena mungkin memiliki implikasi pada data pengguna. Secara khusus, permintaan sudah dicetak sebelumnya jika menggunakan metode selain GET atau POST. Juga, jika POST digunakan untuk mengirim data permintaan dengan Tipe-Konten selain dari aplikasi / x-www-form-urlencoded, multipart / form-data, atau teks / polos, mis. Jika permintaan POST mengirimkan payload XML ke server menggunakan aplikasi / xml atau teks / xml, maka permintaannya sudah disorot. Itu mengatur header kustom dalam permintaan (mis. Permintaan menggunakan header seperti X-PINGOTHER)

    Jika Anda menggunakan pegas hanya menambahkan kode di bawah ini akan menyelesaikan masalah. Di sini saya telah menonaktifkan token csrf yang tidak masalah aktifkan / nonaktifkan sesuai kebutuhan Anda.

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

    Jika Anda menggunakan keamanan pegas, gunakan kode di bawah ini bersama dengan kode di atas.

    @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
sumber
2

Saya mengalami masalah serupa seperti ini, masalah dengan backend. Saya menggunakan server simpul (Express). Saya mendapat permintaan dari frontend (sudut) seperti yang ditunjukkan di bawah ini

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

Tapi itu memberi kesalahan berikutKesalahannya

Ini adalah kode backend yang ditulis menggunakan express tanpa header

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

Setelah menambahkan header ke masalah metode diselesaikan

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

Anda bisa mendapatkan detail lebih lanjut tentang Mengaktifkan CORS di Node JS

Janith Udara
sumber
1

Dijawab sendiri.

CORS angular js + restEasy pada POST

Yah akhirnya saya datang ke solusi ini: Alasannya bekerja dengan IE adalah karena IE mengirim langsung POST, bukan pertama permintaan preflight untuk meminta izin. Tapi saya masih tidak tahu mengapa filter tidak dapat mengelola permintaan OPSI dan mengirimkan dengan header default yang tidak dijelaskan dalam filter (sepertinya menimpa untuk satu-satunya kasus ... mungkin hal yang mudah saja .. .)

Jadi saya membuat jalur PILIHAN di layanan istirahat saya yang menulis ulang respons dan menyertakan header dalam respons menggunakan tajuk respons

Saya masih mencari cara bersih untuk melakukannya jika ada yang menghadapi ini sebelumnya.

J.Apakah
sumber
1

Apache / HTTPD cenderung ada di sebagian besar perusahaan atau jika Anda menggunakan Centos / etc di rumah. Jadi, jika Anda memilikinya, Anda dapat melakukan proxy dengan sangat mudah untuk menambahkan header CORS yang diperlukan.

Saya punya posting blog di sini karena saya menderita dengan itu beberapa kali baru-baru ini. Tetapi yang penting adalah menambahkan ini ke file /etc/httpd/conf/httpd.conf Anda dan pastikan Anda sudah melakukan "Dengarkan 80":

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

Ini memastikan bahwa semua permintaan ke URL di bawah server-ip-Anda: 80 / rute SomePath ke http: // target-ip: 8080 / SomePath (API tanpa dukungan CORS) dan mereka kembali dengan Access-Control-Allow yang benar Header asal untuk memungkinkan mereka bekerja dengan aplikasi web Anda.

Tentu saja Anda dapat mengubah port dan menargetkan seluruh server daripada SomePath jika Anda suka.

John Humphreys - w00te
sumber
1

Jawaban ini menguraikan dua cara untuk mengatasi API yang tidak mendukung CORS:

  • Gunakan Proxy CORS
  • Gunakan JSONP jika API mendukungnya

Salah satu solusinya adalah menggunakan 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>

Untuk informasi lebih lanjut, lihat


Gunakan JSONP jika API mendukungnya:

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

The DEMO pada PLNKR

Untuk informasi lebih lanjut, lihat

georgeawg
sumber
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
sumber
"Dan juga tambahkan kode berikut dalam file WebApiConfig Anda" - Pertanyaannya adalah tentang membuat permintaan ke Flickr. Server mereka tidak berada di bawah kendali OP. Flickr mungkin juga tidak menggunakan ASP.NET.
Quentin
0

kita dapat mengaktifkan CORS di frontend dengan menggunakan modul ngResourse. Tapi yang paling penting, kita harus memiliki kode ini sambil membuat permintaan ajax di controller,

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

Juga, Anda harus menambahkan ngResourse CDN di bagian skrip dan menambahkan dependensi dalam modul aplikasi.

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

Kemudian gunakan "ngResourse" di bagian ketergantungan modul aplikasi

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

Alok Ranjan
sumber