跨域

101 阅读4分钟

1.同源策略

同源策略是什么

同源策略是一种浏览器自带的一种安全策略,它是指网址中的协议、域名、端口三个相同才能互相访问,即协议、域名、端口中有一个不相同,浏览器就不执行与自身不同的脚本。

为什么浏览器有同源策略

因为没有同源策略浏览器就会随便被别人访问,就可以轻松获取我们网址的cookie 信息,或是对网也进行dom操作,这是非常不安全的,cookie 信息,它里面存在着 sessionID ,这是与服务端的 session 会话的重要凭证,如果被别人得到了 cookie ,有很大可能会造成数据被盗取等后果。

同源策略限制内容有那些?

  • 储存在浏览器中的数据localStroage 、 Cookie 和 IndexedDB 不能通过脚本跨域访问;
  • 不能通过脚本操作不同域下的 DOM ;
  • 不能通过 ajax 请求不同域的数据。

加载图片、js、css可以无同源策略

当我们在加载以上类型的 图片、css和js 时,可以无视同源策略。因为像 图片、css文件和js文件 一般可使用 cdn 来进行缓存,而 cdn 一般是外域。同时, js 文件也可以通过 JSONP 来实现跨域。

2、跨域解决方案

### 跨域是什么

所有经过跨越段都得经过serve端配合和允许

未经 server 端允许就实现跨域,说明浏览器有漏洞,是一种危险信号。

JSONP(客户端操作)

JSONP(JSON with Padding)是数据格式 JSON 的一种“使用模式”, 可以让网页从别的网域要数据。 根据 XmlHttpRequest 对象受到同源策略的影响,而利用 数据,而这种使用模式就是所谓的 JSONP 。 用 JSONP 抓到的数据并不是 JSON ,而是任意的 JavaScript ,用 JavaScript 解释器运行而不是用 JSON 解析器解析。 所以,通过 Chrome 查看所有 JSONP 发送的 Get 请求都是 js 类型,而非 XHR

JSONP包含两部分:回调函数和数据

回调函数是当响应到来时要放在当前页面被调用的函数。

数据就是传入回调函数中的 json 数据,也就是回调函数的参数了

function handleResponse(response){
 console.log('The responsed data is: '+response.data);
}
var script = document.createElement('script');
script.src = 'http://www.baidu.com/json/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
/*handleResonse({"data": "zhe"})*/
//原理如下:
//当我们通过script标签请求时
//后台就会根据相应的参数(json,handleResponse)
//来生成相应的json数据(handleResponse({"data": "zhe"}))
//最后这个返回的json数据(代码)就会被放在当前js文件中被执行
//至此跨域通信完成

缺点:

  • 只能使用Get请求
  • 不能注册successerror等事件监听函数,不能很容易的确定 JSONP 请求是否失败。
  • JSONP 是从其他域中加载代码执行,容易受到跨站请求伪造的攻击,其安全性无法确保。

CORS(服务器操作)

cors的原理

CORS (Cross-Origin Resource Sharing),即跨域资源共享,是一种浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,确保安全的跨域数据传输。现代浏览器使用 CORSAPI 容器如 XMLHttpRequest 来减少 HTTP 请求的风险来源。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。 cors 的跨域方法一般是服务端进行操作,服务端需要设置以下 http header :


//设置允许跨域的域名称,不建议直接写“*”
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");

//填写允许跨域的http请求方法
//当 method = OPTIONS 时, 属于预检(复杂请求), 当为预检时, 可以直接返回空响应体, 对应的 http 状态码为 204
response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");

//设置需要支持的跨域请求头,如果设置为*,表明服务器支持所有头信息字段;也可设置为X-Request-With和Content-Type
response.setHeader("Access-Control-Allow-Headers", "X-Request-With, Content-Type");
// 服务器收到请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

//表示具体请求中的媒体类型信息
response.setHeader("Content-Type", "application/json;charset=utf-8");

//设置预检结果的缓存, 单位(秒)
response.setHeader("Access-Control-Max-Age", 86400);

/*如果需要支持 cookies,
 *Access-Control-Allow-Origin 不能设置为 *,
 *并且 Access-Control-Allow-Credentials 需要设置为 true
 *(注意前端请求需要设置 withCredentials = true)
*/
response.setHeader("Access-Control-Allow-Credentials", "false");