簡體   English   中英

如何在 AngularJs 中啟用 CORS

[英]How to enable CORS in AngularJs

我已經使用 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);
        });
    });

但我仍然遇到同樣的錯誤。 以下是我嘗試過的一些鏈接:

XMLHttpRequest 無法加載 URL。 Access-Control-Allow-Origin 不允許的來源

http://goo.gl/JuS5B1

你沒有。 您向其發出請求的服務器必須實施 CORS 才能從您的網站訪問權限授予 JavaScript。 您的 JavaScript 無法授予自己訪問另一個網站的權限。

我有一個類似的問題,對我來說歸結為在接收端響應中添加以下 HTTP 標頭:

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

您可能不希望在末尾使用* ,而只使用發送數據的主機的域名。 *.example.com

但這只有在您有權訪問服務器的配置時才可行。

嘗試使用資源服務消費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>

出現此問題的原因是 Web 應用程序安全模型策略是同源策略在該策略下,Web 瀏覽器允許第一個網頁中包含的腳本訪問第二個網頁中的數據,但前提是兩個網頁具有相同的來源。 這意味着請求者必須匹配請求站點的確切主機、協議和端口。

我們有多種選擇來解決這個 CORS 標頭問題。

  1. 使用代理- 在這個解決方案中,我們將運行一個代理,這樣當請求通過代理時,它看起來就像是某個同源。 如果您使用的是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. 服務器端- 在服務器端,我們需要啟用跨域請求。 首先,我們將獲得預檢請求 (OPTIONS),我們需要允許狀態代碼為200 (ok) 的請求。

    預檢請求首先向其他域上的資源發送 HTTP OPTIONS 請求標頭,以確定實際請求是否可以安全發送。 跨站點請求是這樣預檢的,因為它們可能會對用戶數據產生影響。 特別是,如果請求使用 GET 或 POST 以外的方法,則它會被預檢。 此外,如果 POST 用於發送內容類型不是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 的請求數據,例如,如果 POST 請求向服務器發送 XML 負載使用 application/xml 或 text/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(); } }

我遇到了類似的問題,問題出在后端。 我正在使用節點服務器(Express)。 我有一個來自前端(角度)的 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);
})

您可以獲得有關在 Node JS 上啟用 CORS 的更多詳細信息

本人回答。

CORS angular js + restEasy on POST

最后我找到了這個解決方法:它與 IE 一起工作的原因是因為 IE 直接發送一個 POST 而不是首先請求許可的預檢請求。 但我仍然不知道為什么過濾器無法管理 OPTIONS 請求並通過過濾器中未描述的默認標頭發送(似乎只是這種情況的覆蓋......也許是一個restEasy的事情.. .)

所以我在我的休息服務中創建了一個 OPTIONS 路徑,它重寫響應並使用響應頭在響應中包含頭

如果之前有人遇到過這種情況,我仍在尋找干凈的方法來做到這一點。

Apache/HTTPD 往往存在於大多數企業中,或者如果您在家中使用 Centos/etc。 所以,如果你有它,你可以很容易地做一個代理來添加必要的 CORS 標頭。

我對這個博客張貼在這里,因為我用它最近好幾次遭遇。 但重要的一點是將它添加到您的 /etc/httpd/conf/httpd.conf 文件並確保您已經在做“聽 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),並且它們返回正確的 Access-Control-Allow- Origin 標頭以允許它們與您的網絡應用程序一起使用。

當然,如果您願意,您可以更改端口並針對整個服務器而不是 SomePath。

此答案概述了解決不支持 CORS 的 API 的兩種方法:

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

一種解決方法是使用 CORS 代理:

 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>

有關更多信息,請參閱


如果 API 支持,請使用 JSONP:

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

PLNKR 上演示

有關更多信息,請參閱

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

我們可以使用 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']);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM