• 跨域问题的总结


    跨域方案


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

    什么是同源策略?

    同源是三个相同:“ 域名相同 ” , “ 端口相同 “ , "协议相同"。比如说链接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 CookieLocalStorage IndexDB 无法读取
    2. 2 DOM 无法获得
    3. 3 AJAX 请求不能发送

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

    Cookie 的跨域

    只有同源的网页才能共享cookie
    但是,两个网页一级域名相同,只是二级域名不同,那么有两种解决方法:
    1.  两个页面都设置相同的 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. 跨文档通信APICross-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方法,哪怕不同源,也可以允许跨窗口通信。
    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. 2HTTP的头信息不超出以下几种字段:
    6. Accept
    7. Accept-Language
    8. Content-Language
    9. Last-Event-ID
    10. Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/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的一个实现版本:






  • 相关阅读:
    [转载红鱼儿]delphi 实现微信开发(1)
    Devexpress VCL Build v2013 vol 14.1.3 发布
    [翻译]LSP程序的分类
    睡眠不好
    LuaStudio 9.27 去10分钟退出暗桩板
    vs2012 提示 未能正确加载 "Visual C++ Language Manager Package" 包 的解决办法
    岁月蹉跎
    重新安装系统之前备份
    运动会
    乱思
  • 原文地址:https://www.cnblogs.com/dujuncheng/p/2911baa32adf0332d11352e4471c7b01.html
Copyright © 2020-2023  润新知