跨域问题的总结

跨域方案


问题:



跨域问题的本质是浏览器的同源策略,又称同源政策;

什么是同源策略?

同源是三个相同:“ 域名相同 ” , “ 端口相同 “ , "协议相同"。比如说链接http://www.example.com/dir/page.html  上的网页:

  1. http://www.example.com/dir2/other.html:同源
  2. http://example.com/dir/other.html:不同源(域名不同)
  3. http://v2.www.example.com/dir/other.html:不同源(域名不同)
  4. http://www.example.com:81/dir/other.html:不同源(端口不同)

不同源的页面,A 网站的一个页面setcookie,其他网站(不同源)是拿不到的;

为什么有同源策略?

为了安全,如果A网站一个页面的setCookie,被其他网站拿到了,就可以做坏事了;

同源策略很严格,下面的事情被限制:

  1. (1) Cookie、LocalStorage 和 IndexDB 无法读取
  2. (2) DOM 无法获得
  3. (3) AJAX 请求不能发送

cookie,dom , ajax 不能跨域的解决方案:

Cookie 的跨域

只有同源的网页才能共享cookie

但是,两个网页一级域名相同,只是二级域名不同,那么有两种解决方法:

1.  两个页面都设置相同的 document.domain, cookie 可以共享

举例来说,A网页是‘http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就可以共享Cookie。

  1. document.domain = ‘example.com‘;

如果A,B两个页面都设置了document.domain = ‘ example.com ‘, 那么A B两个页面可以访问到对方的cookies:

在A页面设置了:

  1. document.cookie = ‘name=dudu‘;

在B页面就可以获取到了:

  1. var cookieA = document.cookie

2. 不用在两个页面上设置,服务端设置固定的一级域名;

  1. const express = require(‘express‘);
  2. var serve = express();
  3. serve.use(‘/aaa‘,function(req,res){
  4. res.cookie(‘user‘,‘name‘,{ path:‘/‘, maxAge:24*3600*1000 , domain:.example.com});
  5. res.send(‘ok‘);
  6. })
  7. serve.listen(8888);

iframe跨域

通过iframe 和 window . open ( ), 父窗口获取不到子窗口的dom,子窗口获取不到父窗口的dom;

如果 一级域名相同,二级域名不同,那么和cookie 一样设置相同的 document.domain,就可以了;

如果完全的不相同,有三种方法解决跨域窗口的通信问题:

  1. url #hash
  2. 跨文档通信API(Cross-document messaging)

1. url # 后面改变了, 页面不会刷新,父窗口指定 子窗口的src #hash

  1. var src = originURL + ‘#‘ + data;
  2. document.getElementById(‘myIFrame‘).src = src;

子窗口通过 onhashchange 来接收通知;

  1. window.onhashchange = checkMessage;
  2. function checkMessage() {
  3. var message = window.location.hash;
  4. // ...
  5. }

2.  跨文档通信API 。window对象新增了一个window.postMessage方法,哪怕不同源,也可以允许跨窗口通信。

父窗口http://aaa.com向子窗口http://bbb.com发消息,调用postMessage方法就可以了。

  1. var popup = window.open(‘http://bbb.com‘, ‘title‘);
  2. popup.postMessage(‘Hello World!‘, ‘http://bbb.com‘);

postMessage方法的第一个参数是数据,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。

ajax 跨域

1. nginx 反向代理,设置一个代理服务器, nginx conf.文件里面,设置 proxy 来将请求代理到其他服务器上面

2. jsonp

3. cors

4. websocket

jsonp

图像ping

一个网页可以从任何网页中加载图片,不用担心跨域问题,这也是广告跟踪浏览量的主要方式;

请求的数据是查询字符串带过去的,返回来什么不重要,反正浏览器收不到,浏览器只能知道响应来了没有;

  1. var img = new Image();
  2. img.onload = img.onerror = function () {
  3. alert(‘done!‘);
  4. }
  5. img.src = ‘http://7xvi3w.com1.z0.glb.clouddn.com/cors_CFE74C5D-058B-468C-9D0A-8AD9931214B9.png?name=dudu‘

缺点:只能是get; 收不到具体返回来是什么;

JSONP

jsonp 就是在函数中调用json , jsonp 分为两部分:回调函数  回调函数的参数(数据);回调函数的名字写在查询字符串里面,等请求到浏览器,回调函数会执行,里面的参数就是数据;

原来是<script> 和<img>一样,可以从其他域加载资源,比如从一个国外的网站上获取地址;

  1. function handleResponse (res) {
  2. console.log(res)
  3. }
  4. var script = document.createElement(‘script‘);
  5. script.src = ‘http://freegeoip.net/json/?callback=handleResponse‘;
  6. document.body.insertBefore(script,document.body.firstChild);

后台做了一定的配置,返回字符串 ‘ handleResponse ([ { "name" : "dudu" } ]) ’, 这样我们浏览器的回调函数就会执行;



jsonp 缺点:

1. 它只支持GET请求而不支持POST等其它类型的HTTP请求

2. 它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

3.  jsonp在调用失败的时候不会返回各种HTTP状态码。

4. 缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。

cors

简单原理:

发送一个普通的 get 或者是 post , 没有origin字段,主体内容就是text/plain;

我们新加一个自定义头部,Origin : http:www.example.com:8081  (请求页面的原信息,协议,域名和端口)

如果服务器允许,返回 Access-Control-Allow-Origin :  http:www.example.com:8081 ( 和请求相同的 )

说明服务器允许,再以实际的 HTTP 请求方法发送那个真正的请求。

CORS需要浏览器和服务器同时支持。实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

具体实现:

浏览器将CORS请求分成两类:简单请求非简单请求

区分条件是满足下面两个条件的是简单请求:

  1. 1) 请求方法是以下三种方法之一:
  2. HEAD
  3. GET
  4. POST
  5. (2)HTTP的头信息不超出以下几种字段:
  6. Accept
  7. Accept-Language
  8. Content-Language
  9. Last-Event-ID
  10. Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

不满足这两个条件的,就是非简单请求;

浏览器对于简单请求,直接发送请求,自动加上origin 字段,服务器如果不同意,就返回一个正常的http, xhr.onerror 就知道报错了; 如果同意,会多出来三个字段:

  1. Access-Control-Allow-Origin: http://api.bob.com // 请求的origin ,*
  2. Access-Control-Allow-Credentials: true // 不要发送cookie, 没有该字段,发送cookie 设为true
  3. Access-Control-Expose-Headers: FooBar //getResponseHeader() 只能拿到6个基本字段,多的在这里设置;

6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma

CORS请求默认不发送Cookie。如果要发送,一方面要服务器同意,指定Access-Control-Allow-Credentials字段,另一方面在请求要:

  1. var xhr = new XMLHttpRequest();
  2. xhr.withCredentials = true;

如果不想让cookie  发送,要显示的将xhr.withCredentials 改成false;

对于非简单请求,会在正式通信之前,增加一次"预检"请求;

websocket

websocket 本身就没有同源策略,只要服务器支持,就可以通过它进行跨源通信;使用ws://(非加密)和wss://(加密)作为协议前缀。

  1. GET /chat HTTP/1.1
  2. Host: server.example.com
  3. Upgrade: websocket // 这两行切换成websocket 通信
  4. Connection: Upgrade
  5. Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
  6. Sec-WebSocket-Protocol: chat, superchat
  7. Sec-WebSocket-Version: 13
  8. Origin: http://example.com //表示该请求的请求源(origin),即发自哪个域名。

因为服务器可以根据origin字段,判断是否许可本次通信。如果该域名在白名单内,服务器就会做出如下回应:

  1. HTTP/1.1 101 Switching Protocols
  2. Upgrade: websocket
  3. Connection: Upgrade
  4. Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
  5. Sec-WebSocket-Protocol: chat

扯 websocket 协议……

  1. 一致性验证。比如我们从网上下载了某个文件,网站上一般会给出该文件的MD5值,我们下载下来后,可以利用工具计算出
  2. 新的MD5值,与正确的MD5值进行对照,如果不一样,则可以断定该文件下载出错或被篡改了。
  3. 数字签名。可以用MD5算法对发布的程序或发布的消息生成MD5值作为签名等。
  4. 密码存储。在传输过程中或存储过程中,直接用明文的密码都是很危险的。可以在传输之前先用MD5加密,存储也不用存储
  5. 明文,可以直接存储MD5值。在验证时,先把输入的密码转换成MD5值再与存储值进行对比。
  6. MD5的一个实现版本:

null

时间: 2024-10-13 16:23:23

跨域问题的总结的相关文章

js跨域

第一次写博客,好紧张,不知道能写成啥样,哈哈哈. 自己的一知片解,有错请多多指教,嘻嘻嘻. 一.何为跨域? 只要协议.域名.端口后任何一个不同,就是跨域. 举个例子: http://www.example.com 协议不同 https://www.example.com http://www.example.com 域名不同 http://www.test.com http://www.example.com 端口不同 http://www.example.com:81 注意:ip相同,域名不同

实现AJAX跨域访问方式一

1.添加pom依赖 <dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>cors-filter</artifactId> <version>2.6<ersion> <!--<scope>runtime</scope>--> </dependency> 2.在web.xml 中增加配置 &l

原生jsonp跨域

<script> // jsonp跨域原生写法 var script = document.createElement('script'); script.src = 'http://192.168.7.16/kuayu/test02.php?callback=aa'; document.body.appendChild(script); //aa('后台数据') function aa(res) { alert(res.website); } </script>

跨域cors方法(jsonp,document.domain,document.name)及iframe性质

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作是不同的域. 下表给出了相对 http://store.company.com/dir/page.html 同源检测的结果: 要解决跨域的问题,我们可以使用以下几种方法: 1.通过jsonp跨域[解决ajax跨域] 在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的

什么是跨域?怎么解决跨域问题?

什么是跨域? 跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制. 所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子: http://www.123.com/index.html 调用 http://www.123.com/server.PHP (非跨域) http://www.123.com/index.html 调用 http://www.456.com/server.php (主域名不同:123/456,跨域)

AJAX跨域实现

原理:在同域中建立一个用于请求 别的域的代理程序,并将返回的内容发给客户端,客户端指向同域的这个代理程序 1. 客户端编写 // 其它部分都一样 //2.注册回调方法 callback xmlhttp.onreadystatechange = callback; //获取客户端内容 var userName = document.getElementById("UserName").value; //进行编码解决 中文乱码 userName = encodeURI(encodeURI(

1.NET Core Web Api跨域问题

官方说明 CORS means Cross-Origin Resource Sharing. Refer What is "Same Origin" Part Detailed Procedure 具体实践 需要引入 Microsoft.AspNetCore.Mvc.Cors 包 Cors配置 Startup.cs文件ConfigureServices方法中,将Cors服务放到容器中 services.AddCors(options); 传一个options,指定名字并配置它,这个时候

跨域问题解决方案

一.跨域问题存在的原因 二.跨域解决对比 JSONP对比CORS jsonp和cors都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS 三.CORS跨域解决方案 1.普通Servlet跨域问题解决 http:/

说一说javascript跨域和jsonp

同源策略 在浏览器的安全策略中“同源策略”非常如雷贯耳,说的是协议.域名.端口相同则视为同源,域名也可换成IP地址,不同源的页面脚本不能获取对方的数据. 要是想使用XMLHttpRequest或者常规的AJAX请求获取另一个站点的数据,浏览器会告诉你“XXXX is not allowed by Access-Control-Allow-Orign”. 因为同源策略的存在,防止了跨域访问的安全问题,但同时也损失了方便获取资源的便利. 跨域的src属性 世事又非绝对,浏览器还是允许几个元素跨域访问

iframe跨域访问

js跨域是个讨论很多的话题.iframe跨域访问也被研究的很透了. 一般分两种情况: 一. 是同主域下面,不同子域之间的跨域: 同主域,不同子域跨域,设置相同的document.domian就可以解决; 父页访问子页,可以document.getElementById("myframe").contentWindow.document来访问iframe页面的内容:如果支持contentDocument也可以直接document.getElementById("myframe&