>  기사  >  웹 프론트엔드  >  도메인 간 문제에 대한 매우 상세한 완전한 솔루션(예제 포함)

도메인 간 문제에 대한 매우 상세한 완전한 솔루션(예제 포함)

不言
不言앞으로
2019-01-14 10:05:472572검색

이 기사는 도메인 간 문제에 대한 매우 상세하고 완전한 솔루션(예제 포함)을 제공합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

교차 도메인, 일반적인 문제

간단한 설명

프런트엔드 초보자로서 , 크로스 도메인에 관해서는 JSONP와 CORS만 알 뿐 깊이 이해하지는 못했습니다. 하지만 봄 채용이 가까워질수록 신입사원도 날개를 펄럭여야 한다. 저는 최근 크로스 도메인 문제를 주의 깊게 연구했으며 개발자에게 도움이 되기를 바라며 이 글을 썼습니다. 이 글을 읽기 전에, 다음 사항에 대해 어느 정도 알고 계시기를 바랍니다.

브라우저 원본 정책

nodejs

iframe

docker, nginx

#🎜 🎜#교차 도메인 문제를 연구해야 하는 이유

브라우저의 동일 출처 정책에 따라 한 도메인의 클라이언트는 명시적인 도메인 리소스 없이는 다른 도메인을 읽거나 쓸 수 없습니다. 실제 개발에서는 프런트엔드와 백엔드가 서로 분리되는 경우가 많으며, 프런트엔드와 백엔드 프로젝트 배포가 서버 내부나 서버의 다른 포트 아래에 있지 않은 경우가 많습니다. 프런트 엔드가 백 엔드에서 데이터를 얻으려면 요청을 시작해야 합니다. 요청이 제대로 처리되면 브라우저의 동일 출처 정책에 의해 제한됩니다. 백엔드는 요청을 수신하고 데이터를 반환할 수 있지만 프런트엔드는 데이터를 수신할 수 없습니다.

다중 크로스 도메인 방법

크로스 도메인은 크게 두 가지 목적으로 나눌 수 있습니다

전면 및 백엔드가 분리되어 있으므로 프런트엔드는 백엔드 데이터를 얻기 위해 도메인을 교차합니다

다른 도메인의 프런트엔드 페이지에 대한 도메인 간 통신

#🎜 🎜#프런트엔드와 백엔드의 도메인 간 분리#🎜 🎜#

CORS(Cross Origin Resource Share)

CORS는 도메인 간 리소스 공유 솔루션입니다. . 크로스 도메인 문제를 해결하기 위해 일련의 요청 헤더와 응답 헤더를 추가하여 크로스 사이트 데이터 전송을 표준화하고 보호합니다

요청 헤더에는 주로

이 포함됩니다.

요청 헤더 설명#🎜 🎜 #Origin#🎜 🎜# Origin 헤더는 교차 도메인 요청 또는 사전 요청에서 교차 도메인 요청의 소스 도메인 이름을 나타냅니다. 헤더는 교차 출처 요청에 사용되는 실제 HTTP 방법을 나타내는 데 사용됩니다. -Request-Headers는 사전 요청 시 시작될 교차 도메인 요청에 포함될 요청 헤더 정보를 서버에 알리는 데 사용됩니다 #🎜 🎜#Explanation #🎜🎜 서버 측 검증은 Access-Control-Allow-Origin 헤더에 전달됩니다. 마지막으로 허용된 도메인 간 요청 도메인 이름은 다음과 같습니다. 특정 도메인 이름 또는 *(모든 도메인 이름을 나타냄). Access-Control-Expose-Headers 헤더는 다음 작업에 사용됩니다. 허용 도메인 간 요청에 반환된 응답 헤더 목록입니다. 목록에 있는 응답 헤더의 콘텐츠만 브라우저에서 액세스할 수 있습니다.
응답 헤더에는 주로
#🎜🎜이 포함됩니다. #Response header
Access-Control-Expose-Headers

Access-Control-Max-Age

Access-Control-Max-Age는 이를 알리는 데 사용됩니다. 탐색 브라우저는 캐시 유효 기간 동안 캐시된 사전 확인 결과를 사용하여 교차 도메인 요청을 보낼지 여부를 결정합니다. Access-Control-Allow-Methods는 정보를 알리는 데 사용됩니다. 브라우징 실제로 도메인 간 요청을 보낼 때 서버가 지원할 수 있는 요청 방법은 특정 방법 목록이거나 *(임의의 방법을 나타냄)일 수 있습니다.
Access-Control-Allow-Methods

사용방법

  • 클라이언트는 사양에 따라 요청 헤더만 설정하면 됩니다.

  • 서버는 사양에 따라 해당 응답 헤더를 식별하여 반환하거나 해당 플러그인을 설치하거나 해당 프레임워크 구성 파일을 수정하는 등의 작업을 수행합니다. 서버에서 사용하는 언어와 프레임워크에 따라 다릅니다.

SpringBoot CORS 설정 예시

스프링 boot 프로젝트의 CORS 구성에 대한 코드

HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        String temp = request.getHeader("Origin");
        httpServletResponse.setHeader("Access-Control-Allow-Origin", temp);
        // 允许的访问方法
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
//         Access-Control-Max-Age 用于 CORS 相关配置的缓存
        httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
        httpServletResponse.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept,token");
        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");

JSONP Cross-domain

jsonp의 원칙은 태그. 따라서 동적으로 태그를 생성합니다. src는 대상 인터페이스 + 데이터 패킷 가져오기 + 데이터 처리를 위한 함수 이름입니다. 백엔드는 GET 요청을 받은 후 함수 이름(데이터)을 구문 분석하여 프론트엔드<script> 태그에서 처리 함수를 동적으로 실행합니다<br/>다음 코드를 관찰하세요</script>

#🎜🎜 #프런트엔드 코드

nbsp;html>


    <meta>
    <title>Title</title>


<script>
    var script = document.createElement(&#39;script&#39;);
    script.type = &#39;text/javascript&#39;;

    // 传参并指定回调执行函数为getData
    script.src = &#39;http://localhost:8080/users?username=xbc&callback=handleData&#39;;
    document.body.appendChild(script);
    // 回调执行函数
    function handleData(res) {
        data = JSON.stringify(res)
        console.log(data);
    }
</script>

# 🎜🎜#백엔드 코드(nodejs)
var querystring = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
    var params = querystring.parse(req.url.split('?')[1]);
    var fn = params.callback;

    // jsonp返回设置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    var data = {
        user: 'xbc',
        password: '123456'
    }
    res.write(fn + '(' + JSON.stringify(data) + ')');

    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');

이 예에서 프론트 데스크에서 받은 res는 다음과 같습니다


#🎜🎜 #

도메인 간 문제에 대한 매우 상세한 완전한 솔루션(예제 포함)프런트엔드 페이지는 이렇습니다

#🎜 🎜#

도메인 간 문제에 대한 매우 상세한 완전한 솔루션(예제 포함)

JSONP는 를 사용하므로 GET 요청만 지원할 수 있습니다. 다른 요청은 구현할 수 없습니다nginx 도메인 간 역방향 프록시

Thinking

브라우저에 동일한 출처 정책 제한을 적용한 경우 프런트엔드 프로젝트와 프런트엔드에서 요청한 API 인터페이스 주소를 동일한 소스에 넣을 수 있나요? 웹 서버에서 제공하는 역방향 프록시와 결합하면 프런트엔드나 백엔드에서 별도의 구성 없이 도메인 간 문제를 해결할 수 있습니다. nginx를 예로 들어보세요

백엔드의 실제 배경 주소: http://xxx.xxx.xxx.xxx:8085 배경 주소는 Tomcat을 사용합니다. 배포된 스프링 부트 프로젝트 이름은 gsms_test

nginx 서버 주소: http://xxx.xxx.xxx.xxx:8082입니다. >#🎜🎜 #

Tomcat, nginx 모두 docker로 설정하고 포트포워딩 완료

http://xxx.xxx.xxx.xxx:8085 后台地址使用tomcat部署的spring boot项目 名为gsms_test

nginx服务器地址: http://xxx.xxx.xxx.xxx:8082

tomcat和nginx都是用docker架设的,做了端口转发

使用条件:开发环境为linux系统

nginx /etc/nginx/conf.d/default.conf 사용조건 : 개발환경은 리눅스 시스템입니다

nginx /etc/ nginx/conf.d/default.conf구성 코드는 다음과 같습니다

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        # root   /usr/share/nginx/html/dist; # 前端项目路径
        # index  index.html index.htm;
        proxy_pass http://localhost:8001/; # 前端本机地址,实现自动更新
        autoindex on;
        autoindex_exact_size on;
        autoindex_localtime on;
    }

    location /gsms_test/ {
        proxy_pass 后端真实地址;
    }

    

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

다른 도메인의 페이지는 도메인 간 통신

# 🎜🎜#window.name + iframe cross-domain

window.name은 브라우저의 창에서 공유하는 데이터이며 여전히 존재합니다. 다른 페이지(또는 다른 도메인 이름)를 로드한 후(수정하지 않으면 값이 변경되지 않음) 매우 긴 시간을 지원할 수 있습니다. 이름 값(2MB). 예를 들어 도메인 a의 페이지가 도메인 b의 페이지에서 데이터를 얻으려는 경우 도메인 b의 window.name 값을 수정하면 됩니다. 도메인 a를 도메인 b로 전환하고 다시 전환하여 도메인 b의 window.name 값을 가져올 수 있습니다. 하지만 우리는 개발 중에 페이지를 앞뒤로 전환하고 싶지 않으므로 iframe과 결합해야 합니다.

예제(thinkjs로 구현)

a 도메인 코드는 다음과 같습니다

nbsp;html>


<meta>
<title>A 域</title>


<h1>server A</h1>
<script>
    function getData() {
        var iframe = document.getElementById(&#39;proxy&#39;);
        iframe.onload = function () {
            var name = iframe.contentWindow.name; // 获取iframe窗口里的window.name值
            console.log(name)
        }
        // 由于iframe信息传递也受同源策略限制,所以在window.name被B域修改后,将iframe转回A域下。以便获取iframe的window.name值
        iframe.src = &#39;http://127.0.0.1:8360/sub.html&#39; 
    }
</script>
<iframe>        </iframe>

#🎜🎜 #b 도메인 코드
nbsp;html>


<meta>
<title>New ThinkJS Application</title>


  <h1>server 2</h1>
<script>
  window.name = &#39;user: xbc&#39;;
</script>

Note

동일 출처 정책의 제한으로 인해 상위 페이지는 크로스 도메인 iframe 페이지에서 불완전한 정보를 얻습니다. iframe의 window.name은 다음과 같아야 합니다. 도메인 B를 수정한 후 도메인 A 아래의 아무 페이지로 전환한 다음(window.name은 이쪽에서 수정하면 안 됨) 획득합니다.

교차 도메인 액세스를 위한 프록시 페이지 + iframe

iframe과 상위 페이지 간의 상호 액세스도 동일 출처 정책에 의해 제한되므로 프록시 페이지가 필요합니다. 도메인 간 액세스를 달성합니다.

도메인 간 문제에 대한 매우 상세한 완전한 솔루션(예제 포함)

개인적으로는 좀 번거롭다고 생각하는 분들은 어떻게 되는지 봐주세요. 프런트 엔드는 프록시 페이지를 사용하여 iframe 교차 연결 도메인 액세스 문제를 해결합니까?

Summary

위는 모두 내가 사용하거나 테스트한 도메인 간 방법과 postMessage 및 WebSocket입니다. Cross-domain 방법 및 기타 Cross-domain 방법은 한번도 건드린 적이 없기 때문에 설명하지 않습니다. 프로젝트에서 이러한 방법을 구체적으로 사용하려면 다양한 문제에 대한 구체적인 고려가 필요합니다. 🎜 🎜#

GET 요청만JSONP호환성 및 브라우저 버전 요구 사항 없음CORS호환성 및 브라우저 버전에 대한 요구 사항이 있습니다iframe 또는 서버 역방향 프록시 (리눅스 환경에서 개발)

위 내용은 도메인 간 문제에 대한 매우 상세한 완전한 솔루션(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제