如何在 AngularJs 中启用 CORS

IT技术 javascript angularjs xmlhttprequest cors
2021-01-29 03:18:37

我已经使用 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

6个回答

你没有。您向其发出请求的服务器必须实施 CORS 才能从您的网站访问权限授予 JavaScript。您的 JavaScript 无法授予自己访问另一个网站的权限。

不在评论中可用的空间。这是一个相当大的主题集。
2021-03-16 03:18:37
@AlexLeung — Postman 是一个已安装的应用程序。如果你的网站可以让我的浏览器从谷歌请求数据并阅读它,那么你的网站可以请求我的 GMail 收件箱页面并阅读我的所有电子邮件。那将是可怕的。
2021-03-18 03:18:37
改为从您的服务器向 Flickr 发出请求。
2021-03-31 03:18:37
为什么,我可以从一个响应https://www.google.com使用像邮差的应用程序,但是当我尝试GEThttps://www.google.com使用AJAX调用我得到的CORS错误?有没有办法让 AJAX 调用的行为类似于来自 POSTMAN 的调用?
2021-04-05 03:18:37
我没有使用服务器,但我可以使用 node.js。你能用这个给我指路吗?
2021-04-09 03:18:37

我有一个类似的问题,对我来说归结为在接收端响应添加以下 HTTP 标头

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

您可能不想*在末尾使用 ,而只使用发送数据的主机的域名。喜欢*.example.com

但这只有在您有权访问服务器的配置时才可行。

我是 AngularJs 的新手。请你告诉我在哪里实施这个?
2021-03-16 03:18:37
@Pygirl,我相信您已经将客户端设置为有角度的?您需要向响应服务器端添加标头,具体方式和位置取决于技术。如果它是您从 angularHttp.get()或类似角度调用的 PHP 脚本,请将其添加header('Access-Control-Allow-Origin: *')为被调用的 PHP 脚本中的第一个输出(即在您输出实际响应、JSON 之前)。
2021-03-19 03:18:37
@Ankit 您需要在服务器中添加这些标头,而不是在 AngularJS 中。
2021-03-24 03:18:37
@davidkonrad:我已经在 angular v4 中创建了整个应用程序。你能告诉我必须在哪里包含这些标题吗:/
2021-03-28 03:18:37
@techcraver - 您不需要对服务器配置的操作访问权限 - 只需从脚本中传递标头即可。如果你有一个 PHP 后端,那就是header('Access-Control-Allow-Origin: *');
2021-04-01 03:18:37

尝试使用资源服务消费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 的更多详细信息