浏览器同源策略及跨域解决方案梳理

浏览器同源策略

  • 同源策略:限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。是一个用于隔离潜在恶意文件的重要安全机制。浏览器是从两个方面去做这个同源策略的,一是针对接口的请求,二是针对Dom的查询。
  • 同源定义 两个页面协议/主机/端口(tuple)相同表示两个页面拥有相同的源。以http://www.lickdog.com为例子
https://www.lickdog.com ——> 不同协议
http://www.lickdog.com:9000 ——> 不同端口
http://www.lickpig.top ——> 不同域名

跨域解决方案

  • jsonp

利用HTML标签比如script、img这样的获取资源的标签没有跨域限制,后端返回一个直接执行的方法给前端,由于前端是用script标签发起的请求,所以返回了这个方法后相当于立马执行,并且把要返回的数据放在方法的参数里)。

缺陷,JSONP只能发GET请求。

  • window.name+iframe
  • CORS

CORS是一个W3C标准,全称是"跨域资源共享”(Cross-origin resource sharing),CORS有两种请求,简单请求和非简单请求。

简单请求:

只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:

HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:

Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

非简单请求会发出一次预检测请求,返回码是204,预检测通过才会真正发出请求,这才返回200。这里通过前端发请求的时候增加一个额外的headers来触发非简单请求。

  • 代理

前端请求的时候还是用前端的域名,Nginx之类的代理把这个请求转发到真正的后端域名上

Nginx反向代理解决跨域

在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可。这样,这个服务器上所有url都是相同的域名、协议和端口。因此,对于浏览器来说,这些url都是同源的,没有跨域限制。而实际上,这些url实际上由物理服务器提供服务。

例如:前端应用请求lickdog.com/api 将其转发到11000端口下,规避跨域问题。

server
{
    listen 80;
    server_name lickdog.com www.lickdog.com;
    location /api/ {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:11000/api/;
        set_real_ip_from 0.0.0.0/0;
        real_ip_header  X-Forwarded-For;
        real_ip_recursive   on;
    }
    location / {
        alias /data/web/lickdog/webapp/;
    }
    access_log /data/log/nginx/www.lickdog.com_access.log log_api;
}