跨域

跨域解决方案:

  1. jsonp (常用)
  2. cors (常用)
  3. window.name
  4. document.domain (特定场景)
  5. postMessage (H5)
  6. webpack proxy (webScoket) (常用)

什么是跨域?

拿当前HTML页面的地址和在页面中AJAX请求的API地址做比较:

  • 如果两个地址的协议域名端口号都相同,相当于HTML页面从同一个源下根据某个地址获取数据,属于“同源策略请求”,基于AJAX是可以直接请求到数据的!
  • 如果三者(协议域名端口号)只要有一个不一样,那么就是“非同源策略请求(跨域请求)”,使用AJAX不能直接获取数据了!

HTML页面的地址:http://localhost:8000/A.html
AJAX请求的地址:http://localhost:8000/queryInfo

HTML页面地址:http://localhost:63342/201802LESSON/%E5%85%AC%E5%BC%80%E8%AF%BE/%E8%B7%A8%E5%9F%9F/static/A.html
AJAX请求接口地址:http://localhost:8000/queryInfo

[报错]

Failed to load http://localhost:8000/queryInfo: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:63342' is therefore not allowed access.

跨域的普遍性?

现在的项目一般都是前后端分离的,大部分公司都会把后台的程序用一个新的服务管理,把客户端程序也用一个新的服务管理,两个服务不是同一个源;这样就导致客户端是向其他源发送AJAX请求,跨域成为请求的阻碍问题;

同源:把客户端程序和服务器程序在一个服务中发布!

=======================================

JSONP

在客户端AJAX不允许直接的跨域请求,但是很多东西都可以直接的跨域,例如:script、link、img、iframe等(这些标签的SRC或者HREF设置任何一个资源请求地址,哪怕是其它源下的,也都没有跨域的限制,直接可以把内容获取到 [除非服务器做特殊处理了] =>针对这个特点,真实项目中某些JS文件加载的都是CDN地址)

CORS 跨域资源共享

主要是服务器设置:配置允许跨域的相关头部信息

1
2
3
4
5
6
7
8
9
10
11
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "http://localhost:8000");
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length,Authorization, Accept,X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,HEAD,OPTIONS");
if (req.method === 'OPTIONS') {
res.send('OK!');
return;
}
next();
});

客户端

1
2
3
4
axios.defaults.withCredentials = true;
//=>xhr.withCredentials=true

// axios在某些特定场景下,在发送真实请求之前都会发送一个预请求(OPTIONS)格式的,来验证是否允许跨域

弊端:只能指定一个允许源(不能用通配符和指定多个源),所以目前真实项目中基于CORS实现跨域资源共享是主流方案

WEBPACK代理(webpack proxy)

  1. 安装webpack-dev-server
  2. 配置代理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    proxy: {
    '/api': {
    target: 'https://other-server.example.com',
    changeOrigin: true,
    secure: false,
    pathRewrite: {
    '^/api' : ''
    }
    },
    '/getInfo':{
    target: 'https://other-server.example.com',
    changeOrigin: true
    }
    }

    在CREATE-REACT-APP脚手架中,我们只需要在package.json中设置porxy代理属性,属性值是目标服务器的地址;在客户端发送请求的时候,请求的接口先保证是同源,如果当前源下没有这个接口,没关系,基于dev-server使用webscoket已经把目标代理服务器上的对应接口数据获取到了,所以直接请求同源下没有的接口,也可以获取数据!

===============

基于IFRAME实现跨域

iframe可以实现父页面嵌入子页面(父页面中可以基于js获取子页面中的内容)

  1. window.name
    name是window天生自带的属性,而且有一个特点,同源下,早X页面中设置name的值,页面关掉或者刷新,上次设置的值不消失,能够一直存储最后一次修改的值信息

  2. document.domain
    只能处理主域相同,但是子域不同的情况
    v.qq.com
    s.qq.com

  3. postMessage

-------------本文结束感谢您的阅读-------------