跨域问题(浏览器的同源政策)

为什么浏览器有同源政策

1.含义

最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。

所谓"同源"指的是"三个相同",协议,域名,端口 都相同。

2. 目的

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?

而是在没有同源策略的情况下。当用户在同一个浏览器内,同时打开了银行网站和恶意网站,在没登出时,恶意网站可以通过脚本请求至银行网站,浏览器自动把银行的登陆cookie带上,从而获取到用户的敏感信息,这个过程恶意站根本不需要直接获取银行站的cookie。由于浏览器的无作为,恶意站的这种操作跟用户自己点击是一样的。

很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

3. 限制范围

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送。

虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。

但是有三个标签是允许跨域加载资源:

<img src=XXX>
<link href=XXX>
<script src=XXX>

也就是说你在<div>里面你去请求别的域名下的东西,是请求不到的,但是你用<script src="XXX">去请求就可以请求得到。
这里你或许有个疑问:请求跨域了,那么请求到底发出去没有?

答案是:发出去了
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么Ajax 就不会?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止CSRF,因为请求毕竟是发出去了。

4. 解决方法(AJAX)

这里主要讲AJAX请求产生跨域的解决方法(常见),不讲Cookie之类的

3种方法

  • JSONP
  • WebSocket
  • CORS

JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。
它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

基本原理就是通过动态创建script标签,然后利用src属性进行跨域。

首先,网页动态插入<script>元素,由它向跨源网址发出请求。

function addScriptTag(src) {
     
     
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}

window.onload = function () {
     
     
addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
     
     
console.log('Your public IP address is: ' + data.ip);
};

上面代码通过动态添加<script>元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。

服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。

foo({
     
     
"ip": "8.8.8.8"
});

由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。

CORS 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
这里我就简单的说一说大体流程。

  1. 对于客户端,我们还是正常使用xhr对象发送ajax请求。
    唯一需要注意的是,我们需要设置我们的xhr属性withCredentials为true,不然的话,cookie是带不过去的哦,设置: xhr.withCredentials = true;
  2. 对于服务器端,需要在 response header中设置如下两个字段:
    Access-Control-Allow-Origin: http://www.yourhost.com
    Access-Control-Allow-Credentials:true
    这样,我们就可以跨域请求接口了。

5. 最常用的解决方式

用服务器代理解决(例如常用给Nginx反向代理)
浏览器有跨域限制,但是服务器不存在跨域问题,所以可以由服务器请求所要域的资源再返回给客户端。
画的图有点丑,但是很好理解用nginx解决跨域问题
在这里插入图片描述

参考博客:

http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

http://www.ruanyifeng.com/blog/2016/04/cors.html

https://www.cnblogs.com/bninp/p/5694277.html

猜你喜欢

转载自blog.csdn.net/qq_40733911/article/details/114407609