web-dev-qa-db-ja.com

AngularJsでCORSを有効にする方法

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

それでも私は同じエラーを得ました。これが私が試したいくつかのリンクです:

XMLHttpRequestはURLをロードできません。 OriginはAccess-Control-Allow-Originで許可されていません

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

編集:

@Quentinの提案で、node.jsにプロキシサーバーを作成しました。

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

最終編集

Authorizationヘッダーを削除しました

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

そしてそれはうまくいっている。欲しいものが手に入りました。この質問にご参加いただきありがとうございます

137
ankitr

あなたは違います。あなたが要求しているサーバーはあなたのウェブサイトからJavaScriptを許可するためにCORSを実装しなければなりません。あなたのJavaScriptはそれ自身に他のウェブサイトにアクセスする許可を与えることはできません。

176
Quentin

私は同じような問題を抱えていました、そして私のためにそれは レスポンス 受信側の に次のHTTPヘッダを追加することに煮詰まりました - /:

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

最後に*を使わず、データを送信しているホストのドメイン名だけを使うほうが良いかもしれません。 *.example.comのように

しかし、これはあなたがサーバーの設定にアクセスできる場合にのみ実行可能です。

62
Erwin

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>
9
Ali Habibzadeh

この問題は、Webアプリケーションセキュリティモデルポリシーが 同じ生成元ポリシー であるために発生します。このポリシーでは、Webブラウザは最初のWebページに含まれるスクリプトによる2番目のWebページのデータへのアクセスを許可します。ページは同じ原点を持っています。つまり、要求者は要求サイトの正確なホスト、プロトコル、およびポートを一致させる必要があります。

このCORSヘッダーの問題を解決するには、複数の選択肢があります。

  1. プロキシを使用する - このソリューションでは、リクエストがプロキシを通過するときに同じOriginのように見えるようにプロキシを実行します。 nodeJS を使用している場合は、プロキシの機能を実行するために cors-anywhere を使用できます。 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);
    });
    
  2. _ jsonp _ - JSONPは、クロスドメインの問題を気にせずにJSONデータを送信するための方法です。XMLHttpRequestオブジェクトは使用しません。代わりに<script>タグを使用します。 https://www.w3schools.com/js/js_json_jsonp.asp

  3. サーバー側 - サーバー側ではOrigin間のリクエストを有効にする必要があります。最初にプリフライトリクエスト(OPTIONS)を取得し、ステータスコード 200 (ok)のリクエストを許可する必要があります。

    実際にリクエストを送信しても安全かどうかを判断するために、プリフライトリクエストはまずHTTP OPTIONSリクエストヘッダを他のドメインのリソースに送信します。クロスサイトリクエストはユーザーデータに影響を与える可能性があるため、このようにプリフライトされます。特に、リクエストがGETまたはPOST以外のメソッドを使用している場合、そのリクエストはプリフライトされます。また、POSTがapplication/x-www-form-urlencoded、multipart/form-data、またはtext/plain以外のContent-Typeで要求データを送信するために使用される場合。 POSTリクエストがapplication/xmlまたはtext/xmlを使用してXMLペイロードをサーバーに送信する場合、リクエストはプリフライトされます。それはリクエストにカスタムヘッダを設定します(例えばリクエストはX-PINGOTHERのようなヘッダを使用します)

    spring を使用している場合は、以下のコードを追加するだけで問題は解決します。ここで私はあなたの要件に応じて有効/無効に関係ない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();
        }
    
    }
    
3
Niru

自分で答えた。

CORS角度js + restEasy on POST

ようやく私はこの回避策を思いついた。IEでうまくいったのは、最初に許可を求めるプリフライトリクエストの代わりにIEが直接POSTを送るからだ。しかし、フィルタがOPTIONSリクエストを管理できず、フィルタに記述されていないデフォルトのヘッダで送信できない理由はまだわかりません(その場合だけのオーバーライドのようです...多分restEasyなこと.. 。)

そこで私は私のrestサービスにOPTIONSパスを作成しました。これはレスポンスを書き換え、レスポンスヘッダを使ってヘッダをレスポンスに含めます。

誰かが以前にこれに直面した場合、私はまだそれをするきれいな方法を探しています。

1
J.Doe

私はこのような同様の問題に遭遇しました、問題はバックエンドにありました。 node server(Express)を使用していました。以下に示すように、フロントエンド(角度)からget要求がありました。

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

しかし、次のエラーが発生しました The error

これは、ヘッダーなしで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を有効にする の詳細を取得できます。

1
Janith Udara

Apache/HTTPDは、ほとんどの企業や、自宅でCentosなどを使用している場合に発生する傾向があります。したがって、それがある場合は、必要なCORSヘッダーを追加するためにプロキシを非常に簡単に実行できます。

最近、私はこの here にブログ投稿をしました。しかし重要なのは、これを/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)にルーティングされ、正しいURLで返されるようになります。 Access-Control-Allow-Originヘッダーを使用して、Webアプリと連携できるようにします。

もちろん、ポートを変更してSomePathではなくサーバー全体をターゲットにすることもできます。

        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);
0
shiva samalla

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を追加し、appモジュールに依存関係として追加する必要があります。

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

その後、アプリモジュールの依存関係セクションで "ngResourse"を使用します

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

0
Alok Ranjan