programing

CORS(심포니, jQuery, FOSRest 번들 및 Nelmio Cors 번들 포함)

muds 2023. 9. 3. 16:40
반응형

CORS(심포니, jQuery, FOSRest 번들 및 Nelmio Cors 번들 포함)

⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
TL;DR: 전체를 읽기 전에 편집:

이 문제는 제가 CORS 같은 것과 관련이 없는 코드에서 매우 어리석은 실수를 했기 때문에 해결되었습니다.
이 문제를 읽고 싶다면, 이 문제가 제대로 작동하는 CORS 구성을 가지고 있다는 것에 유의하십시오. 좋은 예를 들어 보겠습니다.

⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️

(노트 끝)

상황.

저는 다중 도메인 Symfony 애플리케이션을 가지고 있는데, 백엔드 부분은 어떤 이유에서인지 고전적인 양식이 아닌 웹 서비스로 데이터를 업데이트합니다.

백엔드: back.mydomain.dev Webservices 도메인: api.mydomain.dev

저는 jQuery를 사용하여 이 웹 서비스에 AJAX를 호출하고 있으며, 개체를 수정하거나 생성하려면 AJAX 요청도 보냅니다. 개체는 Dutrinent 엔티티와 병합되어 지속됩니다.

저는 이 애플리케이션에서 제대로 작동할 GET, PUT, POST 및 DELETE 요청을 만들기 위해 1년 내내 노력해 왔습니다. 그리고 그것들이 서로 다른 도메인에 있다는 이유만으로 저는 제 다른 환경에 CORS를 설치해야 합니다.

세우다

모든 jQuery AJAX 요청은 다음과 같습니다.

ajaxObject = {
    url: 'http://api.mydomain.dev/' + uri,
    type: method, // Can be GET, PUT, POST or DELETE only
    dataType: 'json',
    xhrFields: {
         withCredentials: true
    },
    crossDomain: true,
    contentType: "application/json",
    jsonp: false,
    data: method === 'GET' ? data : JSON.stringify(data) // Here, "data" is ALWAYS containing a plain object. If empty, it equals to "{}"
};

// ... Add callbacks depending on requests

$.ajax(ajaxObject);

그 뒤로는 심포니로 노선을 관리하고 있습니다.

CORS 구성의 경우 다음 구성과 함께 NelmioCorsBundle을 사용합니다.

nelmio_cors:
    paths:
       "^/":
          allow_credentials: true
          origin_regex: true
          allow_origin:
              - "^(https?://)?(back|api)\.mydomain.dev/?"
          allow_headers: ['Origin','Accept','Content-Type']
          allow_methods: ['POST','GET','DELETE','PUT','OPTIONS']
          max_age: 3600
          hosts:
              - "^(https?://)?(back|api)\.mydomain.dev/?"

사용되는 컨트롤러는 FOSRestBundle의 컨트롤러를 확장하고 있으며 일부 보안(예: 올바른 역할이 없을 때 POST/PUT/DELETE할 수 없음)이 있으며 개체를 업데이트할 수 있으며 JSON 데이터만 반환합니다(수신기가 있음).

이상행동

이상적으로, 저는 이것을 원합니다.

  1. jQuery AJAX POST/PUT/DE 요청 실행
  2. 모든 CORS 헤더가 포함된 OPTIONS 요청을 전송해야 합니다.
  3. NelmioCorsBundle은 앱 내에서 컨트롤러를 실행하기 전에도 요청을 수락하는 올바른 CORS 헤더를 반환해야 합니다(번들의 요청 수신기에서 작성).
  4. 수락되면 적절한 HTTP 요청이 (요청 페이로드에 있는) 직렬화된 JSON 문자열로 모든 요청 데이터와 함께 컨트롤러로 전송되고 Symfony는 이를 검색하여 올바른 JSON 문자열을 배열 개체로 해석합니다.
  5. 그런 다음 컨트롤러는 데이터를 가져오고, 데이터의 작업을 수행한 다음 데이터를 반환합니다.application/json대답.

문제

하지만 여기서, 저는 maaaaa의 어떤 조합도 시도해 보았습니다. 그리고 저는 그것을 성공시킬 수 없을 것 같습니다.

n°3 및 4가 완전히 또는 부분적으로 고장났습니다.

사용해 본 해결 방법

  1. 가 연재하지 않을 때는 않을 때data와 함께JSON.stringify(위의 설정 부분 참조) OPTIONS 요청은 전송되지만 FOSRestBundle은BadRequestHttpException격언Invalid json message received그리고 크롬의 개발자 도구에서 볼 수 있는 "요청 페이로드"가 고전이기 때문에 완전히 정상입니다.application/x-www-form-urlencoded내용, 지정한 경우에도contentType: "application/json"jQuery AJAX 요청에서는 직렬화된 JSON 문자열이어야 합니다.

  2. 하지만, 만약 가 시리얼화를 한다면,datavar, "요청 페이로드"는 유효하지만 OPTIONS 요청이 전송되지 않아 CORS 승인이 부족하여 전체 요청이 실패합니다.

  3. 대체할 경우contentType: "application/json"와 함께application/x-www-form-urlencoded또는multipart/form-data데이터를 직렬화하지 않으면 요청 페이로드는 유효하지만 OPTIONS 요청은 전송되지 않습니다.또한 내용 아래에 있는 jQuery의 문서에 설명된 것처럼 정상이어야 합니다.유형 매개 변수:

    참고: 교차 도메인 요청의 경우 내용 유형을 application/x-www-form-urlenced, multipart/form-data 또는 text/plain 이외의 다른 형식으로 설정하면 브라우저가 사전 비행 OPTIONS 요청을 서버로 전송하도록 트리거합니다.

    그런데 어떻게 정확한 CORS 요청을 보낼 수 있습니까?

문의사항

  • 이 문제는 어디에서 발생합니까?
  • 설정에 문제가 있습니까?jQuery로?
  • AJAX 자체로?
  • 이 빌어먹을 문제를 해결하기 위한 다른 해결책은 무엇일까요?

편집(댓글 뒤)

2015-06-29 17:39

조건:

AJAX에서는contentType으로 설정됨application/json.그data옵션이 직렬화된 JSON 문자열로 설정되어 있습니다.

REQUEST 헤더 사전 비행

OPTIONS http://api.mydomain.dev/fr/object/1 HTTP/1.1
Access-Control-Request-Method: POST
Origin: http://back.mydomain.dev
Access-Control-Request-Headers: accept, content-type
Referer: http://back.mydomain.dev/...

응답 헤더 사전 비행

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, DELETE, PUT, OPTIONS
Access-Control-Allow-Headers: origin, accept, content-type
Access-Control-Max-Age: 3600
Access-Control-Allow-Origin: http://back.mydomain.dev

POSTREQUEST 헤더(프리플라이트 후)

POST http://api.mydomain.dev/fr/object/1 HTTP/1.1
Origin: http://back.mydomain.dev
Content-Type: application/json
Referer: http://back.mydomain.dev/...
Cookie: mydomainPortal=v5gjedn8lsagt0uucrhshn7ck1
Accept: application/json, text/javascript, */*; q=0.01

요청 페이로드(원시):{"json":{"id":1,"name":"object"}}

이 경우 Javascript 오류가 발생합니다.

XMLHttpRequest는 http://api.mydomain.dev/fr/object/1을 로드할 수 없습니다.요청한 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다.따라서 오리진 'http://back.mydomain.dev'에 액세스할 수 없습니다.

POST응답 머리글(사전 비행 후)

HTTP/1.1 200 OK
Date: Mon, 29 Jun 2015 15:35:07 GMT
Server: Apache/2.4.12 (Unix) OpenSSL/1.0.2c Phusion_Passenger/5.0.11
Keep-Alive: timeout=5, max=91
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

2015-06-29 17:39

나는 또한 XMLHttpRequest를 만들기 위해 바닐라 자바스크립트를 사용하려고 시도했지만, 문제는 여전히 동일합니다.

var xhr = new XMLHttpRequest;
xhr.open('POST', 'http://api.mydomain.dev/fr/objects/1', true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.withCredentials = true; // Sends cookie
xhr.onreadystatechange = function(e) {
    // A simple callback
    console.info(JSON.parse(e.target.response));
};
// Now send the request with the serialized payload:
xhr.send('{"id":1,"name":"Updated test object"}');

그런 다음 브라우저에서 OPTIONS 요청을 보냅니다.

OPTIONS http://api.mydomain.dev/fr/objects/1 HTTP/1.1
Connection: keep-alive
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://back.mydomain.dev

올바른 응답 헤더를 반환합니다.

Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, DELETE, PUT, OPTIONS
Access-Control-Allow-Headers: origin, accept, content-type
Access-Control-Max-Age: 3600
Access-Control-Allow-Origin: http://back.mydomain.dev

그러나 브라우저는 "Access-Control-*" 헤더 없이 POST 요청을 보냅니다.

사실, 제 설정은 잘 작동했습니다.
정말 완벽하게, 내가 말할 수 있다면요.

그건 그냥 일종의...멍청함.

안 안exit;PHP 파일에 깊이 숨겨져 있습니다.

귀찮게 해서 죄송합니다.SO에 대한 텍스트/품질 비율의 일종의 기록이라고 생각합니다.

편집: 저는 여전히 이 문제가 CORS와 완전히 호환되는 Symfony 프로젝트의 적절한 예가 될 수 있기를 바랍니다.

언급URL : https://stackoverflow.com/questions/31117405/cors-with-symfony-jquery-fosrestbundle-and-nelmiocorsbundle

반응형