처음 JavaScript를 배우기 시작했을 때 ajax cross-domain이 무엇인지 몰랐지만, 몇몇 거물들이 도메인 간 ajax cross-domain 문제에 관해 이야기하는 것을 자주 들었습니다. 오늘은 Ajax 크로스 도메인이 무엇인지, Ajax 크로스 도메인 해결 방법은 무엇인지 알아보겠습니다!
서문
교차 도메인과 관련하여 N 가지 유형이 있습니다. 이 기사에서는 Ajax 요청 교차 도메인에만 중점을 둡니다(Ajax 교차 도메인은 브라우저의 "동일 출처 정책"의 일부일 뿐이며 다른 항목에는 쿠키가 포함됩니다). cross-domain Domain iframe cross-domain, LocalStorage cross-domain 등은 여기에 소개되지 않습니다.) 내용은 대략 다음과 같습니다.
원리성능(일부 발생하는 문제 및 솔루션 구성)
2. Ajax 크로스 도메인 해결 방법
JSONP 방법 CORS 방법
프록시 요청 방법
3. Ajax 크로스 도메인 분석 방법
http 패킷 캡처 분석
몇 가지 예
아약스 크로스란 무엇인가요? -domain
ajax 크로스 도메인의 원칙Ajax의 크로스 도메인 요청 오류 문제가 가장 큰 이유는 브라우저의 "동일 출처 정책" 때문입니다. 브라우저의 동일 출처 정책 및 우회 방법을 참조하세요
CORS 요청 원칙
CORS는 W3C 표준이며 전체 이름은 "교차 출처 리소스 공유"입니다. 이를 통해 브라우저는 교차 출처 서버에 XMLHttpRequest 요청을 발행할 수 있으므로 AJAX가 동일한 출처에서만 사용될 수 있다는 제한을 극복할 수 있습니다. CORS에 대해 읽어보는 것이 좋습니다.도메인 간 리소스 공유를 위한 CORS에 대한 자세한 설명
또한 구현 도식 다이어그램(간단한 버전)도 여기에 컴파일되어 있습니다.
간단한 요청인지 어떻게 판단하나요?
브라우저에서는 CORS 요청을 단순 요청(단순 요청)과 그다지 단순하지 않은 요청(그렇지 않음)의 두 가지 범주로 나눕니다. 간단한 요청). 다음 두 가지 조건이 동시에 충족된다면, 간단한 요청입니다. 1.
요청 방법은 HEAD, GET, POST
3가지 방법 중 하나입니다. 2. HTTP 헤더 정보는 다음 필드를 초과하지 않습니다. 1.
2를 수락합니다. 수용-언어 3. 내용-언어4. 마지막 이벤트-ID 5. Content-Type (application/x-www-form-urlencoded, multipart/form-data, text/plain 3가지 값으로 제한)
위 두 조건을 동시에 충족하지 못하는 요청 단순하지 않은 요청입니다. ajax 크로스 도메인 성능 솔직히 처음에는 글을 정리해서 해결책으로 사용했는데 나중에 보니 아직도 어떻게 하는지 모르시는 분들이 많더라구요 . 시간이 많이 걸리고 노동집약적인 디버깅을 할 수밖에 없습니다. 하지만 분석을 하더라도 해당 성능을 기준으로 크로스 도메인 여부만 판단할 것이므로 이것이 매우 중요합니다. Ajax 요청 시 도메인 간 현상이 발생하고 해결되지 않으면 다음과 같은 동작이 발생합니다. (참고로 이는 ajax 요청입니다. http 요청은 괜찮지만 ajax는 그렇지 않은 이유를 말하지 마세요. , Ajax에는 크로스 도메인이 수반되기 때문입니다. 따라서 단지 http 요청만으로는 충분하지 않습니다.)
참고: 특정 백엔드 크로스 도메인 구성에 대한 질문 개요를 참조하세요.
첫 번째 현상: 요청한 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다, 그리고 응답에 HTTP 상태 코드 404
이러한 현상이 발생합니다.
1. 이 ajax 요청은 "비단순 요청"이므로 요청 전에 사전 요청(OPTIONS)이 전송됩니다. 2. 서버 측 백그라운드 인터페이스는 OPTIONS 요청을 허용하지 않습니다. , 해당 인터페이스를 찾을 수 없습니다. 주소
솔루션: 백엔드에서 옵션 요청을 허용합니다
두 번째 현상:
요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 존재하지 않으며 응답 HTTP 상태 코드가 405
이 현상은 처음과 다릅니다. 이 경우 백그라운드 메소드에서는 OPTIONS 요청을 허용하지만 일부
구성 파일(예: 보안 구성으로) OPTIONS 요청을 차단하면 이 현상이 발생합니다해결책: 백엔드에서 해당 보안 구성을 끄세요
세 번째 현상:
요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다, andstatus 200
이 현상은 1차, 2차와 다릅니다. 이 경우 서버 측 백그라운드에서도 OPTIONS 요청을 허용하고, 인터페이스에서도 OPTIONS 요청을 허용하지만, 다음과 같은 경우에 발생합니다. 헤더가 일치하지 않는 현상
예를 들어 원본 헤더 확인이 일치하지 않습니다. 예를 들어 일부 헤더 지원이 누락된 경우(예: 일반적인 X-Requested-With 헤더) 서버가 응답을 반환합니다. 프런트 엔드가 이 XHR.onerror를 감지하면 프런트 엔드 콘솔에서 오류를 보고하게 됩니다
해결책: 백엔드에 해당 헤더 지원을 추가하세요
네 번째 현상:
heade에 여러 값이 포함되어 있습니다.'* ,*'
증상은 백그라운드 응답의 http 헤더 정보에 Access-Control-Allow-Origin이 두 개 있다는 것입니다:*
솔직히 이 문제의 주된 이유는 도메인 간 구성을 수행하는 사람들이 원리를 이해하지 못하여 다음과 같은 반복 구성이 발생합니다.
1. .net 백엔드에서 공통적입니다(일반적으로 원본은 web.config에서 한 번 구성되고 원본은 다음과 같습니다). 코드에 수동으로 추가됨(예: 코드가 return *을 수동으로 설정함))
2. 공통 .net 백그라운드에서(IIS와 프로젝트 webconfig 모두에서 Origin:* 설정)
솔루션(one- to-one 대응):
1. 코드에 수동으로 추가한 *는 삭제하고 프로젝트 구성에서만 사용하는 것을 권장합니다. 2. IIS에서 구성*을 삭제하고 프로젝트에서만 구성을 사용하는 것이 좋습니다.
Ajax 크로스 도메인 해결 방법
일반적으로 ajax 크로스 도메인 솔루션은 JSONP 또는 CORS를 통해 해결됩니다. (JSONP는 더 이상 사용되지 않으므로 JSONP만 이해하세요.)
교차 도메인 문제를 해결하는 JSONP 방법
jsonp는 교차 도메인 문제를 해결하는 비교적 오래된 솔루션입니다(실제로 권장되지 않음). 여기에 간략한 소개가 있습니다(실제 프로젝트에서 JSONP를 사용하려면 일반적으로 JSONP를 캡슐화하여 Ajax 요청을 하는 JQ 및 기타 클래스 라이브러리를 사용합니다.)
구현 원칙
JSONP를 사용하는 이유 크로스 도메인 솔루션을 해결하는 데 사용할 수 있는 이유는 주로 <script> 도메인 기능을 사용하며 JSONP는 이를 달성하기 위해 이를 활용합니다. 구체적인 원리는 그림과 같습니다</script>
구현 프로세스
JSONP의 구현 단계는 대략 다음과 같습니다(소스의 기사 참조)
1. 클라이언트 웹 페이지는 <script> 요소를 추가하여 서버에서 JSON 데이터를 요청합니다. 동일 출처 정책이 적용됩니다. 2. 서버의 해당 인터페이스는 반환 매개변수 외부에 있습니다. 함수 래핑 레이어를 추가하세요</script>
function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScriptTag('http://example.com/ip?callback=foo'); } function foo(data) { console.log('response data: ' + JSON.stringify(data)); };
3. <script> 요소에서 요청한 스크립트가 코드로 직접 실행됩니다. 이때 브라우저가 foo 함수를 정의하는 한 해당 함수는 즉시 호출됩니다. 매개변수인 JSON 데이터는 문자열이 아닌 </script>
JavaScript 개체로 처리되므로 JSON.parse를 사용하는 단계가 필요하지 않습니다.
일반 JSONP 인터페이스와 일반 인터페이스에서 반환하는 데이터에는 차이가 있으므로 인터페이스가 JSONO와 호환되려면 해당 콜백 키워드 매개변수가 있는지 여부를 판단해야 합니다. JSONP 요청이므로 JSONP 데이터가 반환됩니다. 그렇지 않으면 일반 데이터
사용 참고 사항JSONP의 구현 원칙에 따라 JSONP는 "GET" 요청만 될 수 있습니다. 더 복잡한 POST 및 기타 요청을 하므로 그러한 상황이 발생하면 Cross-domain 아래 CORS 솔루션을 참조해야 합니다(따라서 현재는 기본적으로 제거되었습니다)
CORS는 Cross-domain 문제를 해결합니다
위에서 CORS의 원리를 소개했는데, 여기서 주로 소개하는 것은 실제 프로젝트에서 백엔드를 어떻게 구성해야 하는지에 대한 것입니다. 솔루션:
PHP 배경 구성
PHP 배경 구성은 모든 배경에서 거의 가장 일반적입니다. 아래 단계를 따르세요. 1단계: 도메인 간 허용을 허용하도록 Php 백엔드 구성
foo({ "test": "testData" });
2단계: 구성 Apache 웹 서버 크로스 도메인 (httpd.conf 내)
원본 코드
<?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept'); //主要为跨域CORS配置的两大基本信息,Origin和headers
다음 코드로 변경
<Directory /> AllowOverride none Require all denied </Directory>
Node.js 배경 구성(익스프레스 프레임워크)
Node.js의 배경은 비교적 간단하고 구성할 수 있습니다. Express를 사용하여 다음과 같이 구성하세요.<Directory />
Options FollowSymLinks
AllowOverride none
Order deny,allow
Allow from all
</Directory>
JAVA 배경 구성
JAVA 배경 구성은 다음 단계를 따르기만 하면 됩니다.1단계: 종속 jar 패키지 가져오기
다운로드
cors-filter-1.7 . jar,
java-property-utils-1.9.jar 이 두 라이브러리 파일은 lib 디렉토리에 있습니다. (해당 프로젝트의 webcontent/WEB-INF/lib/ 아래에 배치하세요)2단계: 프로젝트가 Maven으로 빌드된 경우 pom.xml에 다음 종속성을 추가하세요. (Maven이 아닌 경우 무시하세요. )app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1')
//这段仅仅为了方便返回json而已
res.header("Content-Type", "application/json;charset=utf-8");
if(req.method == 'OPTIONS') {
//让options请求快速返回
res.sendStatus(200);
} else {
next();
}
});
그 중 버전은 최신 안정 버전인 CORS
이어야 합니다. 3단계: 프로젝트의 Web.xml(App/WEB-INF/web.xml)에 CORS 구성을 추가합니다.<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>[ version ]</version>
</dependency>
참고하세요 위 구성 파일을 web.xml 앞에 놓고 첫 번째 필터로 존재하십시오(여러 필터가 있을 수 있음)
4단계: 가능한 보안 모듈 구성 오류(일부 프레임워크(예: 회사 전용 프레임워크)에는 보안이 있음에 유의하세요. 모듈 예, 때로는 이러한 보안 모듈 구성이 도메인 간 구성에 영향을 미칠 수 있습니다. 이 경우 먼저 해제해 보세요.)
JAVA Spring Boot 구성
20171230 보충간단한 전역 구성만 나열하세요
<!-- 跨域配置--> <filter> <!-- The CORS filter with parameters --> <filter-name>CORS</filter-name> <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> <!-- Note: All parameters are options, if omitted the CORS Filter will fall back to the respective default values. --> <init-param> <param-name>cors.allowGenericHttpRequests</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.allowOrigin</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.allowSubdomains</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>cors.supportedMethods</param-name> <param-value>GET, HEAD, POST, OPTIONS</param-value> </init-param> <init-param> <param-name>cors.supportedHeaders</param-name> <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value> </init-param> <init-param> <param-name>cors.exposedHeaders</param-name> <!--这里可以添加一些自己的暴露Headers --> <param-value>X-Test-1, X-Test-2</param-value> </init-param> <init-param> <param-name>cors.supportsCredentials</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.maxAge</param-name> <param-value>3600</param-value> </init-param> </filter> <filter-mapping> <!-- CORS Filter mapping --> <filter-name>CORS</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
새 구성, 그런 다음 구성 주석을 추가하면 구성이 성공합니다
PS: 이 방법이 포함되어 있으며 개인적으로 실행하지는 않았지만 피드백에 따르면 이론적으로 가능합니다NET 배경 구성
.NET 배경 구성은 다음 단계를 참조할 수 있습니다. 1단계: 웹 사이트 구성
제어판을 열고 관리 도구를 선택한 다음 웹 사이트를 마우스 오른쪽 버튼으로 클릭하고 찾아보기를 선택합니다. 웹사이트가 있는 디렉터리에 메모장을 사용하여 web.config 파일을 열고 다음 구성 정보를 추가한 후 웹사이트를 다시 시작하세요
请注意,以上截图较老,如果配置仍然出问题,可以考虑增加更多的headers允许,比如:
"Access-Control-Allow-Headers":"X-Requested-With,Content-Type,Accept,Origin"
第二步:其它更多配置,如果第一步进行了后,仍然有跨域问题,可能是:
1、接口中有限制死一些请求类型(比如写死了POST等),这时候请去除限 制
2、接口中,重复配置了Origin:*,请去除即可
3、IIS服务器中,重复配置了Origin:*,请去除即可
代理请求方式解决接口跨域问题
注意,由于接口代理是有代价的,所以这个仅是开发过程中进行的。
与前面的方法不同,前面CORS是后端解决,而这个主要是前端对接口进行代理,也就是:
1、前端ajax请求的是本地接口
2、本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端
3、一般用node.js即可代理
关于如何实现代理,这里就不重点描述了,方法和多,也不难,基本都是基于node.js的。
搜索关键字node.js,代理请求即可找到一大票的方案。
OPTIONS预检的优化
Access-Control-Max-Age:
这个头部加上后,可以缓存此次请求的秒数。
在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据。
非常有用,可以大幅优化请求次数
如何分析ajax跨域
上述已经介绍了跨域的原理以及如何解决,但实际过程中,发现仍然有很多人对照着类似的文档无法解决跨域问题,主要体现在,前端人员不知道什么时候是跨域问题造成的,什么时候不是,因此这里稍微介绍下如何分析一个请求是否跨域:
抓包请求数据
第一步当然是得知道我们的ajax请求发送了什么数据,接收了什么,做到这一步并不难,也不需要fiddler等工具,仅基于Chrome即可
1、Chrome浏览器打开对应发生ajax的页面,F12打开Dev Tools
2、发送ajax请求
3、右侧面板->NetWork->XHR,然后找到刚才的ajax请求,点进去
示例一(正常的ajax请求)
上述请求是一个正确的请求,为了方便,我把每一个头域的意思都表明了,我们可以清晰的看到,接口返回的响应头域中,包括了
Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept Access-Control-Allow-Methods: Get,Post,Put,OPTIONS Access-Control-Allow-Origin: *
所以浏览器接收到响应时,判断的是正确的请求,自然不会报错,成功的拿到了响应数据。
示例二(跨域错误的ajax请求)
为了方便,我们仍然拿上面的错误表现示例举例。
这个请求中,接口Allow里面没有包括OPTIONS,所以请求出现了跨域、
这个请求中,Access-Control-Allow-Origin: *出现了两次,导致了跨域配置没有正确配置,出现了错误。
更多跨域错误基本都是类似的,就是以上三样没有满足(Headers,Allow,Origin),这里不再一一赘述。
示例三(与跨域无关的ajax请求)
当然,也并不是所有的ajax请求错误都与跨域有关,所以请不要混淆,比如以下:
更多
基本上都是这样去分析一个ajax请求,通过Chrome就可以知道了发送了什么数据,收到了什么数据,然后再一一比对就知道问题何在了。
总结
跨域是一个老生常谈的话题,网上也有大量跨域的资料,并且有不少精品(比如阮一峰前辈的),但是身为一个前端人员不应该浅尝而止,故而才有了本文。
위 내용은 크로스 도메인 Ajax에 대한 가장 포괄적인 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!