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 데이터만 반환합니다(수신기가 있음).
이상행동
이상적으로, 저는 이것을 원합니다.
- jQuery AJAX POST/PUT/DE 요청 실행
- 모든 CORS 헤더가 포함된 OPTIONS 요청을 전송해야 합니다.
- NelmioCorsBundle은 앱 내에서 컨트롤러를 실행하기 전에도 요청을 수락하는 올바른 CORS 헤더를 반환해야 합니다(번들의 요청 수신기에서 작성).
- 수락되면 적절한 HTTP 요청이 (요청 페이로드에 있는) 직렬화된 JSON 문자열로 모든 요청 데이터와 함께 컨트롤러로 전송되고 Symfony는 이를 검색하여 올바른 JSON 문자열을 배열 개체로 해석합니다.
- 그런 다음 컨트롤러는 데이터를 가져오고, 데이터의 작업을 수행한 다음 데이터를 반환합니다.
application/json
대답.
문제
하지만 여기서, 저는 maaaaa의 어떤 조합도 시도해 보았습니다. 그리고 저는 그것을 성공시킬 수 없을 것 같습니다.
점 n°3 및 4가 완전히 또는 부분적으로 고장났습니다.
사용해 본 해결 방법
내가 연재하지 않을 때는 않을 때
data
와 함께JSON.stringify
(위의 설정 부분 참조) OPTIONS 요청은 전송되지만 FOSRestBundle은BadRequestHttpException
격언Invalid json message received
그리고 크롬의 개발자 도구에서 볼 수 있는 "요청 페이로드"가 고전이기 때문에 완전히 정상입니다.application/x-www-form-urlencoded
내용, 지정한 경우에도contentType: "application/json"
jQuery AJAX 요청에서는 직렬화된 JSON 문자열이어야 합니다.하지만, 만약 내가 시리얼화를 한다면,
data
var, "요청 페이로드"는 유효하지만 OPTIONS 요청이 전송되지 않아 CORS 승인이 부족하여 전체 요청이 실패합니다.대체할 경우
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
POST
REQUEST 헤더(프리플라이트 후)
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
'programing' 카테고리의 다른 글
jAJAX로 Google 시각화 API 로드 (0) | 2023.09.03 |
---|---|
휴일과 주말을 제외한 두 날짜 사이의 날짜를 어떻게 계산합니까? (0) | 2023.09.03 |
CSS를 사용하여 배경 이미지 중심 맞추기 (0) | 2023.09.03 |
파워셸의 스레드는 어떻게 작동합니까? (0) | 2023.09.03 |
Git에서 원격 분기의 기본 재배치 (0) | 2023.09.03 |