如何在AngularJs中启用CORS

ank*_*itr 141 javascript cors angularjs angularjs-http

我使用JavaScript为Flickr照片搜索API创建了一个演示.现在我将它转换为AngularJs.我在互联网上搜索,发现下面的配置.

组态:

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

服务:

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'}
         });
     }
});
Run Code Online (Sandbox Code Playgroud)

控制器:

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

但我仍然得到同样的错误.以下是我尝试的一些链接:

XMLHttpRequest无法加载URL.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);
Run Code Online (Sandbox Code Playgroud)

最终编辑

我删除了Authorization标头

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

它运行正常.我有我想要的东西.感谢大家参与这个问题

Que*_*tin 182

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

  • 启用CORS的一个很好的指南可以在这里找到:http://enable-cors.org/ (6认同)
  • @AlexLeung - Postman是一个已安装的应用程序.如果您的网站可以让我的浏览器从Google请求数据并阅读它,那么您的网站可以请求我的GMail收件箱页面并阅读我的所有电子邮件.那太可怕了. (5认同)

Erw*_*win 63

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

Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
Run Code Online (Sandbox Code Playgroud)

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

但这只有在您可以访问服务器配置时才可行.

  • @Ankit你需要在**服务器**中添加这些头文件,而不是在AngularJS中. (16认同)
  • 投票支持最后一句话:"但这只有在您访问服务器配置时才可行" (6认同)
  • 我是AngularJs的新手.请问您能告诉我在哪里实施这个? (2认同)
  • @techcraver - 您不需要对服务器配置进行操作访问 - 只需从脚本中传递标头即可。如果您有 PHP 后端,它将是 `header('Access-Control-Allow-Origin: *');` (2认同)

Ali*_*deh 9

尝试使用资源服务来使用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' });
});
Run Code Online (Sandbox Code Playgroud)

模板:

<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>
Run Code Online (Sandbox Code Playgroud)


Nir*_*iru 6

出现此问题的原因是 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);
    });
    
    Run Code Online (Sandbox Code Playgroud)
  2. JSONP - JSONP 是一种发送 JSON 数据的方法,无需担心跨域问题。它不使用 XMLHttpRequest 对象。它使用标签<script>代替。https://www.w3schools.com/js/js_json_jsonp.asp

  3. 服务器端- 在服务器端我们需要启用跨源请求。首先,我们将获取预检请求(选项),并且需要允许状态代码为200(正常)的请求。

    预检请求首先将 HTTP OPTIONS 请求标头发送到其他域上的资源,以确定实际请求是否可以安全发送。跨站点请求会像这样进行预检,因为它们可能会对用户数据产生影响。特别是,如果请求使用 GET 或 POST 以外的方法,则该请求将被预检。另外,如果 POST 用于发送 Content-Type 不是 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("*");
                }
            };
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    如果您使用 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();
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

363818 次

最近记录:

6 年,2 月 前