[javascript] AngularJ에서 CORS를 활성화하는 방법

Flickr 사진 검색 API 용 JavaScript를 사용하여 데모를 만들었습니다. 이제 AngularJ로 변환하고 있습니다. 인터넷에서 검색했으며 아래 구성을 찾았습니다.

구성 :

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를 부여해야합니다. 자바 스크립트는 다른 웹 사이트에 액세스 할 수있는 권한을 스스로 부여 할 수 없습니다.


답변

비슷한 문제가 있었고 수신 측응답 으로 다음 HTTP 헤더를 추가하는 것으로 요약했습니다 .

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

*끝에는 사용하지 말고 데이터를 보내는 호스트의 도메인 이름 만 사용하는 것이 좋습니다 . 처럼*.example.com

그러나 이것은 서버 구성에 액세스 할 수있는 경우에만 가능합니다.


답변

리소스 서비스를 사용하여 깜박임 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>


답변

이 문제는 동일한 원본 정책 인 웹 응용 프로그램 보안 모델 정책으로 인해 발생합니다. 정책 에서 웹 브라우저는 첫 번째 웹 페이지에 포함 된 스크립트가 두 번째 웹 페이지의 데이터에 액세스 할 수 있지만 두 웹 페이지의 원본이 동일한 경우에만 가능합니다. 즉, 요청자는 요청 사이트의 정확한 호스트, 프로토콜 및 포트와 일치해야합니다.

이 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 이외의 Content-Type으로 요청 데이터를 보내는 경우 (예 : 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("*");
                }
            };
        }
    }

    스프링 보안을 사용하는 경우 위 코드와 함께 아래 코드를 사용하십시오.

    @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)를 사용하고있었습니다. 아래 표시된 것처럼 프론트 엔드 (각도)에서 요청을 받았습니다.

   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 앵귤러 js + restEasy on POST

마지막 으로이 해결 방법을 찾았습니다 .IE와 함께 일한 이유는 IE가 먼저 프리 플라이트 요청 대신 POST를 보내서 권한을 요청하기 때문입니다. 그러나 필터가 왜 OPTIONS 요청을 관리 할 수 ​​없었으며 필터에 설명되어 있지 않은 기본 헤더로 전송하는 이유를 여전히 알지 못합니다 (이 경우의 재정의처럼 보입니다 … 아마 restEasy 일 .. .)

그래서 나머지 서비스에서 응답을 다시 작성하고 응답 헤더를 사용하여 응답에 헤더를 포함하는 OPTIONS 경로를 만들었습니다.

아무도 전에이 문제에 직면했을 때 여전히 깨끗한 방법을 찾고 있습니다.


답변

Apache / HTTPD는 대부분의 기업에서 또는 Centos / etc를 집에서 사용하는 경우가 많습니다. 따라서 주변에 있다면 필요한 CORS 헤더를 추가하기 위해 프록시를 매우 쉽게 수행 할 수 있습니다.

최근에 몇 번이나 고통을 겪으면서 여기 에 블로그 게시물이 있습니다 . 그러나 중요한 것은 이것을 /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)로 라우팅 되고 올바른 Access-Control-Allow- 오리진 헤더를 사용하여 웹 앱에서 작동 할 수 있습니다.

물론 원하는 경우 포트를 변경하고 SomePath 대신 전체 서버를 대상으로 지정할 수 있습니다.