**这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战**w
跨域是什么?
1.同源策略
跨域问题其实就是浏览器的同源策略所导致的。
同源策略:是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
当跨域时会收到以下错误
2.同源示例
那么如何才算是同源呢?先来看看 url 的组成部分
http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument
只有当
「protocol(协议)、domain(域名)、port(端口)三者一致。」
才是同源。
以下协议、域名、端口一致。
以下这种看上去再相似也没有用,都不是同源。
在这里注意一下啊,这里是为了突出端口的区别才写上端口。在默认情况下 http 可以省略端口 80, https 省略 443。
如何解决跨域?
CORS
跨域资源共享CORS 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器「不同的域、协议或端口」请求一个资源时,资源会发起一个「跨域 HTTP 请求」**。
「浏览器支持情况」
当你使用 IE<=9, Opera<12, or Firefox<3.5 或者更加老的浏览器,这个时候请使用 JSONP 。
Nginx 反向代理
Nginx 则是通过反向代理的方式。我们可以通过一个例子看一下nginx的配置:
server {
listen 8033;//端口
server_name bj01.reocar.ud_client.com;//代理的域名
//日志
access_log /tmp/udesk.imclient.nginx.access.log;
error_log /tmp/udesk.imclient.nginx.error.log;
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 90d;
add_header Vary "Accept-Encoding";
}
# location ^~ /im_client {proxy_pass http://reocar.ud.com/im_client/;}
location ^~ /static_cmps {
proxy_pass http://****-rd-bj-01.qihh.cn/static_cmps;
}
location ^~ /spa1 {
proxy_pass http://****-rd-bj-01.qihh.cn/spa1;
}
location ^~ /im_client {
proxy_pass http://localhost:3001/;
}
location ^~ /****_im {
proxy_pass http://****-rd-bj-01.qihh.cn/****_im;
}
}
我们可以看到代理的请求路径会将请求转移到我们代理的proxy_pass的服务器地址上。这样我们就实现了nginx的代理。
//nginx的一些操作,
//重启
nginx -s reload
//启动nginx
nginx start
//停止nginx
nginx stop
JSONP
JSONP 主要就是利用了 script 标签没有跨域限制的这个特性来完成的。JSONP的原理非常简单,就是HTML标签中,很多带src属性的标签都可以跨域请求内容,比如我们熟悉的img图片标签。同理,script标签也可以,可以利用script标签来执行跨域的javascript代码。通过这些代码,我们就能实现前端跨域请求数据。
使用限制
仅支持 GET 方法,如果想使用完整的 REST 接口,请使用 CORS 或者其他代理方式。
我们来看一下最简单的JSONP的例子: html代码,直接浏览器打开即可
<html>
<body>
<div>
receive <span id="qwerty"> </span>
</div>
</body>
<script>
function callfun(data) {
document.getElementById('qwerty').innerHTML = data;
}
</script>
<script src="http://127.0.0.1:10010/js?call=callfun"></script>
</html>
后端使用的egg.js,核心代码只有ctx.body那一句
'use strict';
const Controller = require('egg').Controller;
class JsonpController extends Controller {
async index() {
const { ctx } = this;
console.log(ctx.query);
ctx.set('content-type', 'text/javascript');
ctx.body = ctx.query.call + '("nihao")';
}
}
为了让后端知道我们前端的回调函数的名字,我们在script的请求中加入了call=callfun参数,后端接收到ctx.query.call, 再和'("nihao")'合并,最后形成了字符串 callfun("nihao")这一句JS代码,传到前端。
这个"nihao"就是我们从后端跨域传输到前端的数据了。
callfun函数处理这个数据,显示到了屏幕中。
Websocket
WebSocket 规范定义了一种 API,可在网络浏览器和服务器之间建立“套接字”连接。简单地说:客户端和服务器之间存在持久的连接,而且双方都可以随时开始发送数据。
这种方式本质没有使用了 HTTP 的响应头, 因此也没有跨域的限制