什么是跨域?

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。

什么是同源策略?

所谓同源是指,域名,协议,端口均相同。

跨域问题分类

  1. 接口跨域

    前后端分离时,前端为了获取后端数据而跨域。

  2. 前端页面通信

    • jsonp, 利用 script 标签. 但是仅限于 get 请求。
    <script>
         var script = document.createElement('script');
         script.type = 'text/javascript';
    
         // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
         script.src = 'http://www.domain2.com:8080/login?user=admin&callback=getJsonData';
         document.head.appendChild(script);
    
         // 回调执行函数
         function getJsonData(res) {
             alert(JSON.stringify(res));
         }
     </script>
     // 服务端返回:
     getJsonData({"status": true, "user": "admin"})
    
    • 反向代理,通过 Nginx 监听同端口,同域名的访问,不同路径映射到不同的地址。相当于绕过了浏览器端,自然就不存在跨域问题。
    server {
         listen       80;
         server_name  admin.com;
         #charset koi8-r;
         #access_log  logs/host.access.log  main;
    
         location /client { #访问客户端路径
             proxy_pass http://localhost:8080;
             proxy_redirect default;
         }
         location /apis { #访问服务器路径
             rewrite  ^/apis/(.*)$ /$1 break;
             proxy_pass   http://localhost:8081;
        }
     }
    
    • 跨域资源共享-CORS

    不带 cookie,前端无需设置,后端需设置

     header('Access-Control-Allow-Credentials', '*');
    

    带 cookie, 前端后端都需设置。

    axios.defaults.withCredentials = true
    

跨域的请求在服务端会不会真正执行?

这个问题看似简单,但是如果对跨域的理解不到位,那么大概率会答不好。

解题思路

  • 跨域究竟是谁的策略?
  • 在什么时机会拦截请求?
  • 究竟什么时候会发预检请求?
  • 如果有预检,请求什么时候会被真正执行?

跨域请求的拦截

同源策略是浏览器的策略,服务端默认是没有这种策略的。

所以请求的拦截是浏览器

在什么时候拦截

一般解决跨域问题会使用 CORS 解决,客户端会通过服务端返回的一些 Header 去判断该请求是否允许跨域

Access-Control-Allow-Origin 告诉客户端允许请求在哪些 Origin 下被发送,这些 Header 一般都是我们配在服务器上的。

所以是请求发出后,在返回来的时候被浏览器拦截

什么时候会发预检请求

一旦浏览器把请求判定为 简单请求,浏览器就不会发送预检请求了。

浏览器判定请求是否为简单请求要同时满足以下四个条件:

  1. 使用下列方法之一:

  2. GET

  3. HEAD
  4. POST

  5. 只使用了如下的安全 Header,不得人为设置其他 Header

  6. Accept

  7. Accept-Language
  8. Content-Language
  9. Content-Type 的值仅限于下列三者之一:

    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  10. 请求中的任意 XMLHttpRequest 对象均没有注册任何事件监听器;XMLHttpRequest 对象可以使用 XMLHttpRequest.upload 属性访问。

  11. 请求中没有使用 ReadableStream 对象。

总结

跨域的请求有的时候执行,有的时候不执行。 简单请求的情况下,不管是否跨域,一定会到达服务端并被执行,浏览器会隐藏返回值 复杂请求的情况下,先发预检请求,预检请求不会真正执行业务逻辑,预检请求通过后才会发送真正请求并在服务端执行

results matching ""

    No results matching ""