前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript第九弹——探究跨域

JavaScript第九弹——探究跨域

作者头像
萌兔IT
发布2019-07-25 14:41:51
4880
发布2019-07-25 14:41:51
举报
文章被收录于专栏:萌兔it萌兔it萌兔it

Hello小可爱们~~我又来了,还记得昨天说的今天要说什么吗???是滴,今天要说的就是跨域!

同源策略

首先呢,我们要说说,为什么会出现跨域这个东西,不管是面试还是工作总是咬着我们不放,这都源于——同源策略!

同源策略是浏览器最核心、最基本的安全功能,保证了浏览器的正常功能。同源策略要求不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。同源策略的同源指的是域名、协议、端口都相同,如果不是同源的脚本,那么浏览器会在控制台报错,拒绝访问。但是我们可以通过img 的src引用远程图片,通过script标签的src加载远程js,这种情况是不受同源策略影响的,可以视为本地资源,即视为同源。

虽然我们都很讨厌它的存在,那么没有它行不行呢?当然不行!那会造成你所访问的网站极其不安全,更容易受到CSRF、XSS攻击或被迷惑引导进入钓鱼网站。

那么怎样让浏览器不放弃同源策略的保护的情况下,又能够优雅的运行跨域脚本呢~

1

JSONP

JSONP利用<script>标签实现跨域访问,这是一种非常简单的跨域解决方法,但是只能应用GET方法,而且可能被注入恶意代码。

1) 动态插入script标签

2)向服务器请求json数据

3)返回的数据将在回调函数中获取

function addScript(src){

var script = document.createElement('script');

script.setAttribute('type','text/javascript');

script.src = src;

document.body.appendChild(script);

}

//回调函数

function rabbit(data){

console.log('Your rabbit's name is:'+data.name)//所以这里data能够或得到数据

};

window.onload = function(){

addScript('http://mengtuit.com/name?callback=rabbit')//后端将方法放在参数中

}

2

CORS

W3C标准的跨域资源共享。这主要依赖于后端代码,添加Access-Control-Allow-Origin,如果使用了Spring-boot能够更简单的通过注解@crossDomain实现

// 处理成功失败返回格式的工具

class CrossDomain {

static async cors (ctx) {

const query = ctx.request.query

// 如果需要http请求中带上cookie,需要前后端都设置credentials,且后端设置指定的origin

ctx.set('Access-Control-Allow-Origin', 'http://localhost:9099')

ctx.set('Access-Control-Allow-Credentials', true)

// 非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)

// 这种情况下除了设置origin,还需要设置Access-Control-Request-Method以及Access-Control-Request-Headers

ctx.set('Access-Control-Request-Method', 'PUT,POST,GET,DELETE,OPTIONS')

ctx.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, t')

ctx.cookies.set('tokenId', '2')

ctx.body = successBody({msg: query.msg}, 'success')

}

}

3

window

window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

4

HTML5

1) postMessage:otherWindow.postMessage(message, targetOrigin, [transfer]);

允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

2)websocket:HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。

<script>

let socket = new WebSocket('ws://localhost:3000');

socket.onopen = function () {

socket.send('兔兔那么可爱,怎么能吃兔兔!');//向服务器发送数据

}

socket.onmessage = function (e) {

console.log(e.data);//接收服务器返回的数据

}

</script>

5

Nginx

搭建中转nginx服务器,用于转发请求,通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

1. 修改nginx目录下的nginx.conf:

// proxy服务器

server {

listen 80;

server_name www.rabbit1.com;

location / {

proxy_pass http://www.rabbit2.com:8080; #反向代理

proxy_cookie_domain www.rabbit2.com www.rabbit1.com; #修改cookie里域名

index index.html index.htm;

# 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用

add_header Access-Control-Allow-Origin http://www.rabbit1.com; #当前端只跨域不带cookie时,可为*

add_header Access-Control-Allow-Credentials true;

}

}

2. 启动nginx:nginx -s reload

// index.html

var xhr = new XMLHttpRequest();

// 前端开关:浏览器是否读写cookie

xhr.withCredentials = true;

// 访问nginx中的代理服务器

xhr.open('get', 'http://www.rabbit1.com:81/?user=admin', true);

xhr.send();

// server.js

var http = require('http');

var server = http.createServer();

var qs = require('querystring');

server.on('request', function(req, res) {

var params = qs.parse(req.url.substring(2));

// 向前台写cookie

res.writeHead(200, {

'Set-Cookie': 'l=a123456;Path=/;Domain=www.rabbit2.com;HttpOnly' // HttpOnly:脚本无法读取

});

res.write(JSON.stringify(params));

res.end();

});

server.listen('8080');

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

解决跨域的淫奇技巧就先写在这吧,不知道别人,反正我觉得在工作中用到的最多的就是nginx和CORS的方法,其他方法或者不稳定或者有局限性,不过这些也是见仁见智啦~~喜欢兔妞的文章请关注并点击好看让更多人看到哦!如果能打个赏就更加感激不尽了!!!么么哒!!!

最后送大家一道题,看看大家知不知道那些是同源的呢?

1. http://www.a.com/a.js

http://www.a.com/b.js

2. http://www.a.com/a/a.js

http://www.a.com/b/b.js

3. http://www.a.com:8000/a.js

http://www.a.com/b.js

4. http://www.a.com/a.js

https://www.a.com/b.js

5. http://www.a.com/a.js

http://192.168.82.45/b.js

6. http://www.a.com/a.js

http://child.a.com/b.js

7. http://www.a.com/a.js

http://a.com/b.js

8. http://www.a.com/a.js

http://www.b.com/b.js

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 萌兔it 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档