[프런트 엔드 기술] 교차 도메인에 대한 이해에 대해 이야기하십시오.

1. 도메인 간 문제가 발생하는 이유

브라우저의 동일 출처 정책 제한으로 인해. 동일 출처 정책 (Sameoriginpolicy)은 규약으로 브라우저의 핵심이자 가장 기본적인 보안 기능으로 동일 출처 정책이 누락 될 경우 브라우저의 정상적인 기능에 영향을 미칠 수 있습니다. 웹은 동일 출처 정책을 기반으로 구축되고 브라우저는 동일 출처 정책의 구현 일 뿐이라고 할 수 있습니다. 동일 출처 정책은 한 도메인의 JavaScript 스크립트가 다른 도메인의 콘텐츠와 상호 작용하는 것을 방지합니다. 소위 상 동성 (즉, 동일한 도메인에 있음)은 두 페이지가 동일한 프로토콜 (프로토콜) , 호스트 (호스트)포트 번호 (포트)를 가짐을 의미합니다.

둘째, 교차 도메인이란

요청 URL의 프로토콜, 도메인 이름 및 포트 중 하나 가 현재 페이지 URL과 다른 경우 교차 도메인입니다.

현재 페이지 URL 요청 된 페이지의 URL 도메인 간 여부 이유
http://www.test.com/ http://www.test.com/index.html 아니 동일한 소스 (동일한 프로토콜, 도메인 이름 및 포트 번호)
http://www.test.com/ https://www.test.com/index.html 교차 도메인 다른 프로토콜 (http / https)
http://www.test.com/ http://www.baidu.com/ 교차 도메인 메인 도메인 이름이 다릅니다 (test / baidu)
http://www.test.com/ http://blog.test.com/ 교차 도메인 다른 하위 도메인 (www / blog)
http://www.test.com:8080/ http://www.test.com:7001/ 교차 도메인 포트 번호가 다릅니다 (8080/7001).

셋, 비 상동 성의 한계는 무엇입니까

[1] 동일 출처가 아닌 웹 페이지의 쿠키, LocalStorage 및 IndexedDB를 읽을 수 없습니다.

[2] 동일 출처가 아닌 웹 페이지의 DOM에 액세스 할 수 없습니다.

[3] AJAX 요청을 동일하지 않은 소스 주소로 보낼 수 없습니다.

네, 교차 도메인 솔루션

[1] 동일 출처가 아닌 웹 페이지에서 쿠키를 읽을 수없는 문제를 해결하기 위해 document.domain 설정

 JavaScript 동일 출처 정책의 제한으로 인해 스크립트는 자신이 속한 문서와 소스가 동일한 창 및 문서의 속성 만 읽을 수 있습니다.

 이미 성숙한 제품 시스템을 보유한 회사의 경우 서로 다른 페이지가 서로 다른 서버에 배치 될 수 있습니다. 이러한 서버는 서로 다른 도메인 이름을 갖지만 동일한 상위 도메인 이름을 갖습니다.

  • 예를 들어, id.qq.com, www.qq.com, user.qzone.qq.com은 모두 공개 상위 도메인 이름 qq.com을 갖습니다. 이 서버의 페이지 간 도메인 간 액세스는 document.domain을 통해 수행 할 수 있습니다.

document.domain이 같은 페이지는 도메인 이름이 같은 서버에있는 것과 동일합니다. 프로토콜과 포트 번호도 같으면 도메인간에 데이터에 액세스 할 수 있습니다.

사례 연구

(1) 동일 출처 페이지 방문

  1. https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cookie를 엽니 다.
  2. f12 콘솔 창에서 열기 페이지  https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
  3. 다음 그림과 같이 반환 된 창 개체의 문서 속성을 방문하여 성공적으로 액세스 할 수 있는지 확인합니다.

(2) 액세스 프로토콜과 포트 번호가 동일하고 도메인 이름이 일치하지 않지만 상위 도메인 이름이 동일한 페이지 :

  1. id.qq.com 열기 , f12 콘솔 열기 , window.open 페이지 :  www.qq.com ,
  2. 반환 된 창 개체의 문서 속성에 대한 동일한 액세스로 액세스가 실패하고 교차 도메인 양식에 대한 액세스가 차단된다는 메시지가 표시됩니다.

이때 id.qq.com의 document.domain과 www.qq.com의 document.domain을 각각 인쇄하고 전자는 id.qq.com이고 후자는 qq.com임을 확인합니다.

이때 id.qq.com 페이지의 document.domain을 수동으로 설정하고, qq.com으로 설정하고, www.qq.com의 window 개체의 문서를 다시 방문하여 방문이 성공했는지 확인합니다.

[2] 문서 간 통신 API : window.postMessage ()

postMessage 메서드를 호출하여 부모 창 http://test1.com을 구현하여 자식 창 http://test2.com에 메시지를 보냅니다 (하위 창도이 메서드를 통해 부모 창에 메시지를 보낼 수 있음).

다음 문제를 해결하는 데 사용할 수 있습니다.

  • 페이지와 열린 새 창 간의 데이터 전송
  • 여러 창 사이에 전달되는 메시지
  • 페이지 및 중첩 된 iframe 메시징
  • 위의 세 가지 시나리오에서 도메인 간 데이터 전송
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
 
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');

메시지 이벤트를 호출하여 상대방이 보낸 메시지를 모니터링합니다.

// 监听 message 消息
window.addEventListener('message', function (e) {
  console.log(e.source); // e.source 发送消息的窗口
  console.log(e.origin); // e.origin 消息发向的网址
  console.log(e.data);   // e.data   发送的消息
},false);

【3】JSONP

JSONP는 서버와 클라이언트 간의 출처 간 통신을위한 일반적인 방법입니다. 가장 큰 특징은 간단한 응용 프로그램, 좋은 호환성 (IE의 하위 버전과 호환)이지만, 단점은 게시 요청이 아닌 가져 오기 요청 만 지원한다는 것입니다.

핵심 아이디어 : 웹 페이지 <script>元素하나를 추가 하여 서버에서 JSON 데이터를 요청하고 서버 요청을 수신하면 지정된 이름의 콜백 함수의 매개 변수 위치로 데이터를 다시 보냅니다.

① 네이티브 실현 :

<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
 
// 处理服务器返回回调函数的数据
<script type="text/javascript">
    function dosomething(res){
        // 处理获得的数据
        console.log(res.data)
    }
</script>

② jQuery 아약스 :

$.ajax({
    url: 'http://www.test.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",    // 自定义回调函数名
    data: {}
});

③ Vue.js

this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

【4】CORS

CORS는 Cross-Origin Resource Sharing의 약어입니다. W3C 표준이며 교차 출처 AJAX 요청을위한 기본 솔루션입니다.

  • 일반 교차 도메인 요청 : 서버 측에서 Access-Control-Allow-Origin 만 설정하면됩니다.
  • 쿠키를 사용한 교차 도메인 요청 : 프런트 엔드와 백 엔드를 모두 설정해야합니다.

4.1 [프런트 엔드 설정] xhr.withCredentials 필드에 따라 쿠키 유무 확인

① 원생 ajax

var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
 
// 前端设置是否带cookie
xhr.withCredentials = true;
 
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
 
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
    }
};

② jQuery 아약스 

$.ajax({
   url: 'http://www.test.com:8080/login',
   type: 'get',
   data: {},
   xhrFields: {
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
});
 
 

③vue-resource

Vue.http.options.credentials = true

④ 축 

axios.defaults.withCredentials = true

4.2 [서버 설정]

CORS에 대한 서버 측 지원은 주로 Access-Control-Allow-Origin을 설정하여 수행됩니다. 브라우저가 해당 설정을 감지하면 Ajax가 도메인 간 액세스를 수행하도록 허용 할 수 있습니다.

① 자바 배경

/*
 * 导入包:import javax.servlet.http.HttpServletResponse;
 * 接口参数中定义:HttpServletResponse response
 */
 
// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 
 
// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
response.setHeader("Access-Control-Allow-Credentials", "true"); 
 
// 提示OPTIONS预检时,后端需要设置的两个常用自定义头
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

② Nodejs 배경

var http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    var postData = '';
 
    // 数据块接收中
    req.addListener('data', function(chunk) {
        postData += chunk;
    });
 
    // 数据接收完毕
    req.addListener('end', function() {
        postData = qs.parse(postData);
 
        // 跨域后台设置
        res.writeHead(200, {
            'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
            'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议+域名+端口)
            /* 
             * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),
             * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问
             */
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'  // HttpOnly的作用是让js无法读取cookie
        });
 
        res.write(JSON.stringify(postData));
        res.end();
    });
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

③ PHP 배경

<?php
 header("Access-Control-Allow-Origin:*");

④ Apache는 기본적으로 활성화되는 HTTP 헤더 설정을 활성화하기 위해 mod_headers 모듈을 사용해야합니다. Apache 구성 파일의 <Directory>, <Location>, <Files> 또는 <VirtualHost> 구성에 다음 내용 만 추가하면됩니다.

Header set Access-Control-Allow-Origin *

 

 

추천

출처blog.csdn.net/qq_41893274/article/details/113615552