精华内容
下载资源
问答
  • Java黑科技之源:JVMTI完全解读

    万次阅读 2019-06-26 07:00:00
    Java生态中有一些非常规的技术,它们能达到一些特别的效果。这些技术的实现原理不去深究的话一般并不是广为人知。这种技术通常被称为黑科技。而这些黑科技中的绝...

            Java生态中有一些非常规的技术,它们能达到一些特别的效果。这些技术的实现原理不去深究的话一般并不是广为人知。这种技术通常被称为黑科技。而这些黑科技中的绝大部分底层都是通过JVMTI实现的。

           形象地说,JVMTI是Java虚拟机提供的一整套后门。通过这套后门可以对虚拟机方方面面进行监控,分析。甚至干预虚拟机的运行。

           下面先介绍下哪些黑科技是通过JVMTI实现的,再详细的介绍JVMTI。

     


    JVMTI可以用来实现哪些黑科技

    1. 使用JVMTI对class文件加密

      有时一些涉及到关键技术的class文件或者jar包我们不希望对外暴露,因而需要进行加密。使用一些常规的手段(例如使用混淆器或者自定义类加载器)来对class文件进行加密很容易被反编译。反编译后的代码虽然增加了阅读的难度,但花费一些功夫也是可以读懂的。使用JVMTI我们可以将解密的代码封装成.dll,或.so 文件。这些文件想要反编译就很麻烦了,另外还能加壳。解密代码不能被破解,从而也就保护了我们想要加密的class文件。


    2. 使用JVMTI实现应用性能监控(APM)

      在微服务大行其道的环境下,分布式系统的逻辑结构变得越来越复杂。这给系统性能分析和问题定位带来了非常大的挑战。基于JVMTI的APM能够解决分布式架构和微服务带来的监控和运维上的挑战。APM通过汇聚业务系统各处理环节的实时数据,分析业务系统各事务处理的交易路径和处理时间,实现对应用的全链路性能监测。开源的Pinpoint, ZipKin, Hawkular,商业的AppDynamics,OneAPM,Google Dapper等都是个中好手。


    3. 产品运行时错误监测及调试

      想要看生产环境的异常,最原始的方式是登录到生产环境的机器查看日志。稍微高级一点的方式是通过日志监控或者APM等工具将异常采集上来。但是这些手段都有许多明显的缺点。首先,不是所有的异常都会被打印到日志中,有些异常可能被代码吃掉了;其次,打印异常的时候通常只有异常堆栈信息,异常发生时上下文的变量值很难获取到(除非有经验的程序员将其打印出来了),而这些信息对定位异常的原因至关重要。基于JVMTI可以开发出一款工具来时事监控生产环境的异常。这方面有一款成熟的商业软件OverOps,其有三个主要的功能:1. 采集到所有的异常,包括try catch之后没有打印出来的异常;2. 可以采集到异常发生时上下文所有变量的值;3. 可以将异常发生的堆栈对应的源代码采集展示出来,从而在一个系统上就可以看代码定位问题,不需要打开ide调试源代码。


    4. JAVA程序的调试(debug)。

      一般JAVA的IDE都自带了调试工具。例如Eclipse的调试器相信大部分人都使用过。它的调试器org.eclipse.jdt.debug插件底层就是调用的JVMTI来实现的。不仅如此,随着服务云化的发展,google甚至推出了云端调试工具cloud debugger。它时一个web应用,可以直接对生产环境进行远程调试,不需要重启或者中断服务。阿里也有类似的工具Zdebugger。


    5. JAVA程序的诊断(profile)。

      当出现cpu使用率过高、线程死锁等问题时,需要使用一些JAVA性能剖析或者诊断工具来分析具体的原因。例如Alibaba开源的Java诊断工具Arthas,深受开发者喜爱。Arthas的功能十分强大,它可以查看或者动态修改某个变量的值、统计某个方法调用链上的耗时、拦截方法前后,打印参数值和返回值,以及异常信息等。


    6. 热加载

      热加载指的是在不重启虚拟机的情况下重新加载一些class。热加载可以使本地调试代码非常节省时间,不用每次更新代码都重启一边程序。同时,在一线不方便重启的线上环境也能派上用场。这方面的代表产品有商业产品JRebel等。JRebel能够对应用中的任何class起作用。

     


    JVMTI是什么

     

    1. JVMTI的定义及原理

      在介绍JVMTI之前,需要先了解下Java平台调试体系JPDA(Java PlatformDebugger Architecture)。它是Java虚拟机为调试和监控虚拟机专门提供的一套接口。如下图所示,JPDA被抽象为三层实现。其中JVMTI就是JVM对外暴露的接口。JDI是实现了JDWP通信协议的客户端,调试器通过它和JVM中被调试程序通信。

            JVMTI 本质上是在JVM内部的许多事件进行了埋点。通过这些埋点可以给外部提供当前上下文的一些信息。甚至可以接受外部的命令来改变下一步的动作。外部程序一般利用C/C++实现一个JVMTIAgent,在Agent里面注册一些JVM事件的回调。当事件发生时JVMTI调用这些回调方法。Agent可以在回调方法里面实现自己的逻辑。JVMTIAgent是以动态链接库的形式被虚拟机加载的。



      640?wx_fmt=png



    2. JVMTI的历史

      JVMTI 的前身是JVMDI(Java Virtual Machine Profiler Interface) 和 JVMPI(Java Virtual Machine Debug Interface),它们原来分别被用于提供调试 Java 程序以及 Java 程序调节性能的功能。在 J2SE 5.0 之后 JDK 取代了JVMDI 和 JVMPI 这两套接口,JVMDI 在最新的 Java SE 6 中已经不提供支持,而 JVMPI 也计划在 Java SE 7 后被彻底取代。


    3. JVMTI的功能

      JVMTI处于整个JPDA 体系的最底层,所有调试功能本质上都需要通过 JVMTI 来提供。从大的方面来说,JVMTI 提供了可用于 debug 和profiler 的接口;同时,在 Java 5/6 中,虚拟机接口也增加了监听(Monitoring),线程分析(Thread analysis)以及覆盖率分析(Coverage Analysis)等功能。从小的方面来说包含了虚拟机中线程、内存、堆、栈、类、方法、变量,事件、定时器处理等等诸多功能。具体可以参考oracle 的文档:https://docs.oracle.com/javase/1.5.0/docs/guide/jvmti/jvmti.html。通过这些接口,开发人员不仅可以调试在该虚拟机上运行的 Java 程序,还能查看它们运行的状态,设置回调函数,控制某些环境变量,从而优化程序性能。


    4. JVMTI的实现

      JVMTI 并不一定在所有的 Java 虚拟机上都有实现,不同的虚拟机的实现也不尽相同。不过在一些主流的虚拟机中,比如 Sun 和 IBM,以及一些开源的如Apache Harmony DRLVM 中,都提供了标准 JVMTI 实现。

     

     

    参考:

    1. https://docs.oracle.com/javase/1.5.0/docs/guide/jvmti/jvmti.html

    2. https://www.ibm.com/developerworks/cn/java/j-lo-jpda2/

    3. http://blog.caoxudong.info/blog/2017/12/07/jvmti_reference

    4. http://lovestblog.cn/blog/2015/09/14/javaagent/

    5. https://www.jianshu.com/p/e59c4eed44a2

     

     

     


    展开全文
  • 一文带你了解 HTTP 黑科技

    万次阅读 多人点赞 2020-01-31 10:37:07
    在前面两篇文章中我们讲述了 HTTP 的入门,HTTP 所有常用标头的概述,这篇文章我们来聊一下 HTTP 的一些 黑科技。 HTTP 内容协商 什么是内容协商 在 HTTP 中,内容协商是一种用于在同一 URL 上提供资源的不同表示...

    这是 HTTP 系列的第三篇文章,此篇文章为 HTTP 的进阶文章。

    在前面两篇文章中我们讲述了 HTTP 的入门,HTTP 所有常用标头的概述,这篇文章我们来聊一下 HTTP 的一些 黑科技

    HTTP 内容协商

    什么是内容协商

    在 HTTP 中,内容协商是一种用于在同一 URL 上提供资源的不同表示形式的机制。内容协商机制是指客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为适合的资源。内容协商会以响应资源的语言、字符集、编码方式等作为判断的标准。

    内容协商的种类

    内容协商主要有以下3种类型:

    • 服务器驱动协商(Server-driven Negotiation)

    这种协商方式是由服务器端进行内容协商。服务器端会根据请求首部字段进行自动处理

    • 客户端驱动协商(Agent-driven Negotiation)

    这种协商方式是由客户端来进行内容协商。

    • 透明协商(Transparent Negotiation)

    是服务器驱动和客户端驱动的结合体,是由服务器端和客户端各自进行内容协商的一种方法。

    内容协商的分类有很多种,主要的几种类型是 Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language

    一般来说,客户端用 Accept 头告诉服务器希望接收什么样的数据,而服务器用 Content 头告诉客户端实际发送了什么样的数据。

    为什么需要内容协商

    我们为什么需要内容协商呢?在回答这个问题前我们先来看一下 TCP 和 HTTP 的不同。

    在 TCP / IP 协议栈里,传输数据基本上都是 header+body 的格式。但 TCP、UDP 因为是传输层的协议,它们不会关心 body 数据是什么,只要把数据发送到对方就算是完成了任务。

    而 HTTP 协议则不同,它是应用层的协议,数据到达之后需要告诉应用程序这是什么数据。当然不告诉应用这是哪种类型的数据,应用也可以通过不断尝试来判断,但这种方式无疑十分低效,而且有很大几率会检查不出来文件类型。

    所以鉴于此,浏览器和服务器需要就数据的传输达成一致,浏览器需要告诉服务器自己希望能够接收什么样的数据,需要什么样的压缩格式,什么语言,哪种字符集等;而服务器需要告诉客户端自己能够提供的服务是什么。

    所以我们就引出了内容协商的几种概念,下面依次来进行探讨

    内容协商标头

    Accept

    接受请求 HTTP 标头会通告客户端自己能够接受的 MIME 类型

    那么什么是 MIME 类型呢?在回答这个问题前你应该先了解一下什么是 MIME

    MIME: MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。

    也就是说,MIME 类型其实就是一系列消息内容类型的集合。那么 MIME 类型都有哪些呢?

    文本文件: text/html、text/plain、text/css、application/xhtml+xml、application/xml

    图片文件: image/jpeg、image/gif、image/png

    视频文件: video/mpeg、video/quicktime

    应用程序二进制文件: application/octet-stream、application/zip

    比如,如果浏览器不支持 PNG 图片的显示,那 Accept 就不指定image/png,而指定可处理的 image/gif 和 image/jpeg 等图片类型。

    一般 MIME 类型也会和 q 这个属性一起使用,q 是什么?q 表示的是权重,来看一个例子

    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    

    这是什么意思呢?若想要给显示的媒体类型增加优先级,则使用 q= 来额外表示权重值,没有显示权重的时候默认值是1.0 ,我给你列个表格你就明白了

    qMIME
    1.0text/html
    1.0application/xhtml+xml
    0.9application/xml
    0.8* / *

    也就是说,这是一个放置顺序,权重高的在前,低的在后,application/xml;q=0.9 是不可分割的整体。

    Accept-Charset

    Accept-charset 属性规定服务器处理表单数据所接受的字符编码;Accept-charset 属性允许你指定一系列字符集,服务器必须支持这些字符集,从而得以正确解释表单中的数据。

    Accept-Charset 没有对应的标头,服务器会把这个值放在 Content-Type中用 charset=xxx来表示,

    例如,浏览器请求 GBK 或 UTF-8 的字符集,然后服务器返回的是 UTF-8 编码,就是下面这样

    Accept-Charset: gbk, utf-8
    Content-Type: text/html; charset=utf-8
    

    Accept-Language

    首部字段 Accept-Language 用来告知服务器用户代理能够处理的自然语言集(指中文或英文等),以及自然语言集的相对优先级。可一次指定多种自然语言集。和 Accept 首部字段一样,按权重值 q= 来表示相对优先级。

    Accept-Language: en-US,en;q=0.5
    

    Accept-Encoding

    表示 HTTP 标头会标明客户端希望服务端返回的内容编码,这通常是一种压缩算法。Accept-Encoding 也是属于内容协商 的一部分,使用并通过客户端选择 Content-Encoding 内容进行返回。

    即使客户端和服务器都能够支持相同的压缩算法,服务器也可能选择不压缩并返回,这种情况可能是由于这两种情况造成的:

    • 要发送的数据已经被压缩了一次,第二次压缩并不会导致发送的数据更小
    • 服务器过载,无法承受压缩带来的性能开销,通常,如果服务器使用 CPU 超过 80% ,Microsoft 则建议不要使用压缩

    下面是 Accept-Encoding 的使用方式

    Accept-Encoding: gzip
    Accept-Encoding: compress
    Accept-Encoding: deflate
    Accept-Encoding: br
    Accept-Encoding: identity
    Accept-Encoding: *
    Accept-Encoding: deflate, gzip;q=1.0, *;q=0.5
    

    上面的几种表述方式就已经把 Accept-Encoding 的属性列全了

    • gzip: 由文件压缩程序 gzip 生成的编码格式,使用 Lempel-Ziv编码(LZ77)和32位CRC的压缩格式,感兴趣的同学可以读一下 (https://en.wikipedia.org/wiki/LZ77_and_LZ78#LZ77)

    • compress: 使用Lempel-Ziv-Welch(LZW)算法的压缩格式,有兴趣的同学可以读 (https://en.wikipedia.org/wiki/LZW)

    • deflate: 使用 zlib 结构和 deflate 压缩算法的压缩格式,参考 (https://en.wikipedia.org/wiki/Zlib) 和 (https://en.wikipedia.org/wiki/DEFLATE)

    • br: 使用 Brotli 算法的压缩格式,参考 (https://en.wikipedia.org/wiki/Brotli)

    • 不执行压缩或不会变化的默认编码格式

    • * : 匹配标头中未列出的任何内容编码,如果没有列出 Accept-Encoding ,这就是默认值,并不意味着支

      持任何算法,只是表示没有偏好

    • ;q= 采用权重 q 值来表示相对优先级,这点与首部字段 Accept 相同。

    Content-Type

    Content-Type 实体标头用于指示资源的 MIME 类型。作为响应,Content-Type 标头告诉客户端返回的内容的内容类型实际上是什么。Content-type 有两种值 : MIME 类型和字符集编码,例如

    Content-Type: text/html; charset=UTF-8
    

    在某些情况下,浏览器将执行 MIME 嗅探,并且不一定遵循此标头的值;为防止此行为,可以将标头 X-Content-Type-Options 设置为 nosniff。

    Content-Encoding

    Content-Encoding 实体标头用于压缩媒体类型,它让客户端知道如何进行解码操作,从而使客户端获得 Content-Type 标头引用的 MIME 类型。表示如下

    Content-Encoding: gzip
    Content-Encoding: compress
    Content-Encoding: deflate
    Content-Encoding: identity
    Content-Encoding: br
    Content-Encoding: gzip, identity
    Content-Encoding: deflate, gzip
    

    Content-Language

    Content-Language 实体标头用于描述面向受众的语言,以便使用户根据用户自己的首选语言进行区分。例如

    Content-Language: de-DE
    Content-Language: en-US
    Content-Language: de-DE, en-CA
    

    下面根据内容协商对应的请求/响应标头,我列了一张图供你参考,注意其中 Accept-Charset 没有对应的 Content-Charset ,而是通过 Content-Type 来表示。

    HTTP 认证

    HTTP 提供了用于访问控制和身份认证的功能,下面就对 HTTP 的权限和认证功能进行介绍

    通用 HTTP 认证框架

    RFC 7235 定义了 HTTP 身份认证框架,服务器可以根据其文档的定义来检查客户端请求。客户端也可以根据其文档定义来提供身份验证信息。

    请求/响应的工作流程如下:服务器以401(未授权) 的状态响应客户端告诉客户端服务器需要认证信息,客户端提供至少一个 www-Authenticate 的响应标头进行授权信息的认证。想要通过服务器进行身份认证的客户端可以在请求标头字段中添加认证标头进行身份认证,一般的认证过程如下

    首先客户端发起一个 HTTP 请求,不带有任何认证标头,服务器对此 HTTP 请求作出响应,发现此 HTTP 信息未带有认证凭据,服务器通过 www-Authenticate标头返回 401 告诉客户端此请求未通过认证。然后客户端进行用户认证,认证完毕后重新发起 HTTP 请求,这次 HTTP 请求带有用户认证凭据(注意,整个身份认证的过程必须通过 HTTPS 连接保证安全),到达服务器后服务器会检查认证信息,如果不符合服务器认证信息,会返回 403 Forbidden 表示用户认证失败,如果满足认证信息,则返回 200 OK

    我们知道,客户端和服务器之间的 HTTP 连接可以被代理缓存重新发送,所以认证信息也适用于代理服务器。

    代理认证

    由于资源认证和代理认证可以共存,因此需要不同的头和状态码,在代理的情况下,会返回状态码 407(需要代理认证)Proxy-Authenticate 响应头包含至少一个适用于代理的情况,Proxy-Authorization请求头用于将证书提供给代理服务器。下面分别来认识一下这两个标头

    Proxy-Authenticate

    HTTP Proxy-Authenticate 响应标头定义了身份验证方法,应使用该身份验证方法来访问代理服务器后面的资源。它将请求认证到代理服务器,从而允许它进一步发送请求。例如

    Proxy-Authenticate: Basic
    Proxy-Authenticate: Basic realm="Access to the internal site"
    

    Proxy-Authorization

    这个 HTTP 请求标头和上面的 Proxy-Authenticate 拼接很相似,但是概念不同,这个标头用于向代理服务器提供凭据,例如

    Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
    

    下面是代理服务器的请求/响应认证过程

    这个过程和通用的过程类似,我们就不再详细展开描述了。

    禁止访问

    如果代理服务器收到的有效凭据不足以获取对给定资源的访问权限,则服务器应使用403 Forbidden状态代码进行响应。与 401 Unauthorized407 Proxy Authorization Required 不同,该用户无法进行身份验证。

    WWW-Authenticate 和 Proxy-Authenticate 头

    WWW-AuthenticateProxy-Authenticate 响应头定义了获得对资源访问权限的身份验证方法。他们需要指定使用哪种身份验证方案,以便希望授权的客户端知道如何提供凭据。它们的一般表示形式如下

    WWW-Authenticate: <type> realm=<realm>
    Proxy-Authenticate: <type> realm=<realm>
    

    我想你从上面看到这里一定会好奇 <type>realm是什么东西,现在就来解释下。

    • <type> 是认证协议,Basic 是下面协议中最普遍使用的

    RFC 7617 中定义了Basic HTT P身份验证方案,该方案将凭据作为用户ID /密码对传输,并使用 base64 进行编码。(感兴趣的同学可以看看 https://tools.ietf.org/html/rfc7617)

    其他的认证协议主要有

    认证协议参考来源
    Basic查阅 RFC 7617,base64编码的凭据
    Bearer查阅 RFC 6750,承载令牌来访问受 OAuth 2.0保护的资源
    Digest查阅 RFC 7616,Firefox仅支持md5哈希,请参见错误bug 472823以获得SHA加密支持
    HOBA查阅 RFC 7486
    Mutual查阅 RFC 8120
    AWS4-HMAC-SHA256查阅 AWS docs
    • realm 用于描述保护区或指示保护范围,这可能是诸如 Access to the staging site(访问登陆站点) 或者类似的,这样用户就可以知道他们要访问哪个区域。

    Authorization 和 Proxy-Authorization 标头

    Authorization 和 Proxy-Authorization 请求标头包含用于通过代理服务器对用户代理进行身份验证的凭据。在此,再次需要类型,其后是凭据,取决于使用哪种身份验证方案,可以对凭据进行编码或加密。一般表示如下

    Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
    Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
    

    HTTP 缓存

    通过把请求/响应缓存起来有助于提升系统的性能,Web 缓存减少了延迟和网络传输量,因此减少资源获取锁需要的时间。由于链路漫长,网络时延不可控,浏览器使用 HTTP 获取资源的成本较高。所以,非常有必要把数据缓存起来,下次再请求的时候尽可能地复用。当 Web 缓存在其存储中具有请求的资源时,它将拦截该请求并直接返回资源,而不是到达源服务器重新下载并获取。这样做可以实现两个小目标

    • 减轻服务器负载
    • 提升系统性能

    下面我们就一起来探讨一下 HTTP 缓存都有哪些

    不同类型的缓存

    HTTP 缓存有几种不同的类型,这些可以分为两个主要类别:私有缓存共享缓存

    • 共享缓存:共享缓存是一种缓存,它可以存储多个用户重复使用的请求/响应。
    • 私有缓存:私有缓存也称为专用缓存,它只适用于单个用户。
    • 不缓存过期资源:所有的请求都会直接到达服务器,由服务器来下载资源并返回。

    我们主要探讨浏览器缓存代理缓存,但真实情况不只有这两种缓存,还有网关缓存,CDN,反向代理缓存和负载平衡器,把它们部署在 Web 服务器上,可以提高网站和 Web 应用程序的可靠性,性能和可伸缩性。

    不缓存过期资源

    不缓存过期资源即浏览器和代理不会缓存过期资源,客户端发起的请求会直接到达服务器,可以使用 no-cache 标头代表不缓存过期资源。

    no-cache 属于 Cache-Control 通用标头,其一般的表示方法如下

    Cache-Control: no-cache
    

    也可以使用 max-age = 0 来实现不缓存的效果。

    Cache-Control: max-age=0
    

    私有缓存

    私有缓存只用来缓存单个用户,你可能在浏览器设置中看到了 缓存,浏览器缓存包含服务器通过 HTTP 下载下来的所有文档。这个高速缓存用于使访问的文档可以进行前进/后退,保存操作而无需重新发送请求到源服务器。

    可以使用 private 来实现私有缓存,这与 public 的用法相反,缓存服务器只对特定的客户端进行缓存,其他客户端发送过来的请求,缓存服务器则不会返回缓存。它的一般表示方法如下

    Cache-Control: private
    

    共享缓存

    共享缓存是一种用于存储要由多个用户重用的响应缓存。共享缓存一般使用 public 来表示,public 属性只出现在客户端响应中,表示响应可以被任何缓存所缓存。一般表示方法如下

    Cache-Control: public
    

    缓存控制

    HTTP/1.1 中的 Cache-Control 常规标头字段用于执行缓存控制,使用此标头可通过其提供的各种指令来定义缓存策略。下面我们依次介绍一下这些属性

    不缓存

    no-store 才是真正意义上的不缓存,每次服务器接受到客户端的请求后,都会返回最新的资源给客户端。

    Cache-Control: no-store
    

    缓存但需要验证

    同上面的 不缓存过期资源

    私有和共享缓存

    同上

    缓存过期

    缓存中一个很重要的指令就是max-age,这是资源被视为新鲜的最长时间 ,与 Expires 相反,此指令是相对于请求时间的。对于应用程序中不会更改的文件,通常可以添加主动缓存。下面是 mag-age 的表示

    Cache-Control: max-age=31536000
    

    缓存验证

    must-revalidate 表示缓存必须在使用之前验证过时资源的状态,并且不应使用过期的资源。

    Cache-Control: must-revalidate
    

    下面是一个缓存验证图

    什么是新鲜的数据

    一旦资源存储在缓存中,理论上就可以永远被缓存使用。但是不管是浏览器缓存还是代理缓存,其存储空间是有限的,所以缓存会定期进行清除,这个过程叫做 缓存回收(cache eviction) (自译)。另一方面,服务器上的缓存也会定期进行更新,HTTP 作为应用层的协议,它是一种客户-服务器模式,HTTP 是无状态的协议,因此当资源发生更改时,服务器无法通知缓存和客户端。因此服务器必须通过某种方式告知客户端缓存已经被更新。服务器会提供过期时间这个概念,告知客户端在此到期时间之前,资源是新鲜的,也就是未更改过的。在此到期时间的范围之外,资源已过时。过期算法(Eviction algorithms) 通常会将新资源优先于陈旧资源使用。

    这里需要注意一下,过期的资源并不会被回收或忽略,当高速缓存接收到过期资源时,它会使用 If-None-Match 转发此请求,以检查它是否仍然有效。如果有效,服务器会返回 304 Not Modified响应头并且没有任何响应体,从而节省了一些带宽。

    下面是使用共享缓存代理的过程

    这个图应该比较好理解,只说一下 Age 的作用,Age 是 HTTP 响应标头告诉客户端源服务器在多久之前创建了响应,它的单位为,Age 标头通常接近于0,如果是0则可能是从源服务器获取的,如果不是表示可能是由代理服务器创建,那么 Age 的值表示的是缓存后的响应再次发起认证到认证完成的时间值

    缓存的有效性是由多个标头来共同决定的,而并非某一个标头来决定。如果指定了 Cache-control:max-age=N ,那么缓存会保存 N 秒。如果这个通用标头不存在的话,则会检查是否存在 Expires 标头。如果 Exprires 标头存在,那么它的值减去 Date 标头的值就可以确定其有效性。最后,如果max-ageexpires 都不存在,就去寻找 Last-Modified 标头,如果存在此标头,则高速缓存的有效性等于 Date 标头的值减去 Last-modified 标头的值除以10。

    缓存验证

    当到达缓存资源的有效期时,将对其进行验证或再次获取。仅当服务器提供了强验证器弱验证器时,才可以进行验证。

    当用户按下重新加载按钮时,将触发重新验证。如果缓存的响应包含 Cache-control:must-revalidate标头,则在正常浏览下也会触发该事件。另一个因素是 高级 -> 缓存首选项 面板中的缓存验证首选项。有一个选项可在每次加载文档时强制进行验证。

    Etag

    我们上面提到了强验证器和弱验证器,实现验证器功能的标头正式 Etag 的作用,这意味着 HTTP 用户代理(例如浏览器)不知道该字符串表示什么,并且无法预测其值。如果 Etag 标头是资源响应的一部分,则客户端可以在未来请求的标头中发出 If-None-Match,以验证缓存的资源。

    Last-Modified响应标头可以用作弱验证器,因为它只有1秒可以分辨的时间。如果响应中存在 Last-Modified标头,则客户端可以发出 If-Modified-Since请求标头来验证缓存资源。(关于 Etag 更多我们会在条件请求介绍)

    避免碰撞

    通过使用 Etag 和 If-Match 标头,你可以检测避免碰撞。

    例如,在编辑 MDN 时,将对当前 Wiki 内容进行哈希处理并将其放入响应中的 Etag 中

    Etag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
    

    当将更改保存到 Wiki 页面(发布数据)时,POST 请求将包含 If-Match 标头,其中包含 Etag 值以检查有效性。

    If-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
    

    如果哈希值不匹配,则表示文档已在中间进行了编辑,并返回 412 Precondition Failed 错误。

    缓存未占用资源

    Etag 标头的另一个典型用法是缓存未更改的资源,如果用户再次访问给定的 URL(已设置Etag),并且该 URL过时,则客户端将在 If-None-Match 标头字段中发送其 Etag 的值

    If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
    

    服务器将客户端的 Etag(通过 If-None-Match 发送)与 Etag 进行比较,以获取其当前资源版本,如果两个值都匹配(即资源未更改),则服务器会发回 304 Not Modified状态,没有主体,它告诉客户端响应的缓存仍然可以使用。

    HTTP CROS 跨域

    CROS 的全称是 Cross-Origin Resource Sharing(CROS),中文译为 跨域资源共享,它是一种机制。是一种什么机制呢?它是一种让运行在一个域(origin)上的 Web 应用被准许访问来自不同源服务器上指定资源的机制。在搞懂这个机制前,你需要线了解什么是 域(origin)

    Origin

    Web 概念中域(Origin) 的内容由scheme(protocol) - 协议host(domain) - 主机和用于访问它的 URL port - 端口定义。仅仅当 scheme 、host、port 都匹配时,两个对象才有相同的来源。这种协议相同,域名相同,端口相同的安全策略也被称为 同源策略(Same Origin Policy)。某些操作仅限于具有相同来源的内容,可以使用 CORS 取消此限制。

    跨域的特点

    • 下面是跨域问题的例子,看看你是否清楚什么是跨域了
    (1) http://example.com/app1/index.html
    (2) http://example.com/app2/index.html
    

    上面这两个 URL 是否具有跨域问题呢?

    上面两个 URL 是不具有跨域问题的,因为这两个 URL 具有相同的协议(scheme)主机(host)

    • 那么下面这两个是否具有跨域问题呢?
    http://Example.com:80
    http://example.com
    

    这两个 URL 也不具有跨域问题,为什么不具有,端口不一样啊。其实它们两个端口是一样的。

    或许你会认为这两个 URL 是不一样的,放心,关于一样不一样的论据我给你抛出来了

    协议和域名部分是不区分大小写的,但是路径部分则根据服务器平台而定。Windows 和 Mac OS X 系统是不区分大小写的,而采用UNIX和Linux系的服务器系统是区分大小写的,

    也就是说上面的 Example.comexample.com 其实是一个网址,并且由于两个地址具有相同的 scheme 和 host ,默认情况下服务器通过端口80传递 HTTP 内容,所以上面这两个地址也是相同的。

    • 下面这两个 URL 地址是否具有跨域问题?
    http://example.com/app1
    https://example.com/app2
    

    这两个 URL 的 scheme 不同,所以这两个 URL 具有跨域问题

    • 再看下面这三个 URL 是否具有跨域问题
    http://example.com
    http://www.example.com
    http://myapp.example.com
    

    这三个 URL 也是具有跨域问题的,因为它们隶属于不通服务器的主机 host。

    • 下面这两个 URL 是否具有跨域问题
    http://example.com
    http://example.com:8080
    

    这两个 URL 也是具有跨域问题,因为这两个 URL 的默认端口不一样。

    同源策略

    处于安全的因素,浏览器限制了从脚本发起跨域的 HTTP 请求。 XMLHttpRequest 和其他 Fetch 接口 会遵循 同源策略(same-origin policy)。也就是说使用这些 API 的应用程序想要请求相同的资源,那么他们应该具有相同的来源,除非来自其他来源的响应包括正确的 CORS 标头也可以。

    同源策略是一种很重要的安全策略,它限制了从一个来源加载的文档或脚本如何与另一个来源的资源进行交互。 它有助于隔离潜在的恶意文档,减少可能的攻击媒介。

    我们上面提到,如果两个 URL 具有相同的协议、主机和端口号(如果指定)的话,那么两个 URL 具有相同的来源。下面有一些实例,你判断一下是不是具有相同的来源

    目标来源 http://store.company.com/dir/page.html

    URLOutcomeReason
    http://store.company.com/dir2/other.html相同来源只有path不同
    http://store.company.com/dir/inner/another.html相同来源只有path不同
    https://store.company.com/page.html不同来源协议不通
    http://store.company.com:81/dir/page.html不同来源默认端口不同
    http://news.company.com/dir/page.html不同来源主机不同

    现在我带你认识了两遍不同的源,现在你应该知道如何区分两个 URL 是否属于同一来源了吧!

    好,你现在知道了什么是跨域问题,现在我要问你,哪些请求会产生跨域请求呢?这是我们下面要讨论的问题

    跨域请求

    跨域请求可能会从下面这几种请求中发出:

    1. 调用 XMLHttpRequest 或者 Fetch api。

    XMLHttpRequest 是什么?(我是后端程序员,前端不太懂,简单解释下,如果解释的不好,还请前端大佬们不要胖揍我)

    所有的现代浏览器都有一个内置的 XMLHttpReqeust 对象,这个对象可以用于从服务器请求数据。

    XMLHttpReqeust 对于开发人员来说很重要,XMLHttpReqeust 对象可以用来做下面这些事情

    • 更新网页无需重新刷新页面
    • 页面加载后从服务器请求数据
    • 页面加载后从服务端获取数据
    • 在后台将数据发送到服务器

    使用 XMLHttpRequest(XHR) 对象与服务器进行交互,你可以从 URL 检索数据从而不必刷新整个页面,这使网页可以更新页面的一部分,而不会中断用户的操作。XMLHttpRequest 在 AJAX 异步编程中使用很广泛。

    再来说一下 Fetch API 是什么,Fetch 提供了请求和响应对象(以及其他网络请求)的通用定义。它还提供了相关概念的定义,例如 CORS 和 HTTP Origin 头语义,并在其他地方取代了它们各自的定义。

    1. Web 字体(用于 CSS 中@ font-face中的跨域字体使用),以便服务器可以部署 TrueType 字体,这些字体只能由允许跨站点加载和使用的网站使用。
    2. WebGL 纹理
    3. 使用 drawImage() 绘制到画布上的图像/视频帧
    4. 图片的 CSS 形状

    跨域功能概述

    跨域资源共享标准通过添加新的 HTTP 标头来工作,这些标头允许服务器描述允许哪些来源从 Web 浏览器读取信息。另外,对于可能导致服务器数据产生副作用的 HTTP 请求方法(尤其是 GET 或者具有某些 MIME 类型 POST 方法以外 HTTP 方法),该规范要求浏览器预检请求,使用 HTTP OPTIONS 请求方法从服务器请求受支持的方法,然后在服务器批准后发送实际请求。服务器还可以通知客户端是否应与请求一起发送凭据(例如 Cookies 和 HTTP 身份验证)。

    注意:CORS 故障会导致错误,但是出于安全原因,该错误的详细信息不适用于 JavaScript。 所有代码都知道发生了错误。 确定具体出问题的唯一方法是查看浏览器的控制台以获取详细信息。

    访问控制

    下面我会和大家探讨三种方案,这些方案都演示了跨域资源共享的工作方式。所有这些示例都使用XMLHttpRequest,它可以在任何支持的浏览器中发出跨站点请求。

    简单请求

    一些请求不会触发 CORS预检(关于预检我们后面再介绍)。简单请求是满足一下所有条件的请求

    • 允许以下的方法:GETHEADPOST

    • 除了由用户代理自动设置的标头(例如 Connection、User-Agent 或者在 Fetch 规范中定义为禁止标头名称的其他标头)外,唯一允许手动设置的标头是那些 Fetch 规范将其定义为 CORS安全列出的请求标头 ,它们是:

      • Accept
      • Accept-Language
      • Content-Language
      • Content-Type(下面会介绍)
      • DPR
      • Downlink
      • Save-Data
      • Viewport-Width
      • Width
    • Content-Type 标头的唯一允许的值是

      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain
    • 没有在请求中使用的任何 XMLHttpRequestUpload 对象上注册事件侦听器;这些可以使用XMLHttpRequest.upload 属性进行访问。

    • 请求中未使用 ReadableStream对象。

      例如,假定 web 内容 https://foo.example 想要获取 https://bar.other 域的资源,那么 JavaScript 中的代码可能会像下面这样写

      const xhr = new XMLHttpRequest();
      const url = 'https://bar.other/resources/public-data/';
         
      xhr.open('GET', url);
      xhr.onreadystatechange = someHandler;
      xhr.send(); 
      

    这使用 CORS 标头来处理特权,从而在客户端和服务器之间执行某种转换。

    让我们看看在这种情况下浏览器将发送到服务器的内容,并让我们看看服务器如何响应:

    GET /resources/public-data/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Connection: keep-alive
    Origin: https://foo.example
    

    注意请求的标头 Origin ,它表明调用来自于 https://foo.example。让我们看看服务器是如何响应的

    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 00:23:53 GMT
    Server: Apache/2
    Access-Control-Allow-Origin: *
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Transfer-Encoding: chunked
    Content-Type: application/xml
    
    […XML Data…]
    

    服务端发送 Access-Control-Allow-Origin 作为响应。使用 Origin 标头和 Access-Control-Allow-Origin 展示了最简单的访问控制协议。在这个事例中,服务端使用 Access-Control-Allow-Origin 作为响应,也就说明该资源可以被任何域访问。

    如果位于https://bar.other的资源所有者希望将对资源的访问限制为仅来自https://foo.example的请求,他们应该发送如下响应

    Access-Control-Allow-Origin: https://foo.example
    

    现在除了 https://foo.example 之外的任何域都无法以跨域方式访问到 https://bar.other 的资源。

    预检请求

    和上面探讨的简单请求不同,预检请求首先通过 OPTIONS 方法向另一个域上的资源发送 HTTP 请求,用来确定实际请求是否可以安全的发送。跨站点这样被预检,因为它们可能会影响用户数据。

    下面是一个预检事例

    const xhr = new XMLHttpRequest();
    xhr.open('POST', 'https://bar.other/resources/post-here/');
    xhr.setRequestHeader('X-PINGOTHER', 'pingpong');
    xhr.setRequestHeader('Content-Type', 'application/xml');
    xhr.onreadystatechange = handler;
    xhr.send('<person><name>Arun</name></person>'); 
    

    上面的事例创建了一个 XML 请求体用来和 POST 请求一起发送。此外,设置了非标准请求头 X-PINGOTHER ,这个标头不是 HTTP/1.1 的一部分,但通常对 Web 程序很有用。由于请求的 Content-Type 使用 application/xml,并且设置了自定义标头,因此该请求被预检。如下图所示

    如下所述,实际的 POST 请求不包含 Access-Control-Request- * 标头;只有 OPTIONS 请求才需要它们。

    下面我们来看一下完整的客户端/服务器交互,首先是预检请求/响应

    OPTIONS /resources/post-here/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Connection: keep-alive
    Origin: http://foo.example
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: X-PINGOTHER, Content-Type
    
    
    HTTP/1.1 204 No Content
    Date: Mon, 01 Dec 2008 01:15:39 GMT
    Server: Apache/2
    Access-Control-Allow-Origin: https://foo.example
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    Access-Control-Max-Age: 86400
    Vary: Accept-Encoding, Origin
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    

    上面的1 -11 行代表预检请求,预检请求使用 OPYIIONS 方法,浏览器根据上面的 JavaScript 代码段所使用的请求参数确定是否需要发送此请求,以便服务器可以响应是否可以使用实际请求参数发送请求。OPTIONS 是一种 HTTP / 1.1方法,用于确定来自服务器的更多信息,并且是一种安全的方法,这意味着它不能用于更改资源。请注意,与 OPTIONS 请求一起,还发送了另外两个请求标头(分别是第9行和第10行)

    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: X-PINGOTHER, Content-Type
    

    Access-Control-Request-Method 标头作为预检请求的一部分通知服务器,当发送实际请求时,将使用POST 请求方法发送该请求。

    Access-Control-Request-Headers 标头通知服务器,当发送请求时,它将与X-PINGOTHER 和 Content-Type 自定义标头一起发送。服务器可以确定这种情况下是否接受请求。

    下面的 1 - 11行是服务器发回的响应,表示POST 请求和 X-PINGOTHER 是可以接受的,我们着重看一下下面这几行

    Access-Control-Allow-Origin: http://foo.example
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    Access-Control-Max-Age: 86400
    

    服务器完成响应表明源 http://foo.example 是可以接受的 URL,能够允许 POST、GET、OPTIONS 进行请求,允许自定义标头 X-PINGOTHER, Content-Type。最后,Access-Control-Max-Age 以秒为单位给出一个值,这个值表示对预检请求的响应可以缓存多长时间,在此期间内无需发送其他预检请求。

    完成预检请求后,将发送实际请求:

    POST /resources/post-here/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Connection: keep-alive
    X-PINGOTHER: pingpong
    Content-Type: text/xml; charset=UTF-8
    Referer: https://foo.example/examples/preflightInvocation.html
    Content-Length: 55
    Origin: https://foo.example
    Pragma: no-cache
    Cache-Control: no-cache
    
    <person><name>Arun</name></person>
    
    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:15:40 GMT
    Server: Apache/2
    Access-Control-Allow-Origin: https://foo.example
    Vary: Accept-Encoding, Origin
    Content-Encoding: gzip
    Content-Length: 235
    Keep-Alive: timeout=2, max=99
    Connection: Keep-Alive
    Content-Type: text/plain
    
    [Some GZIP'd payload]
    

    正式响应中很多标头我们在之前的文章已经探讨过了,本篇不再做详细的介绍,读者可以参考
    你还在为 HTTP 的这些概念头疼吗? 查阅

    带凭证的请求

    XMLHttpRequest 或 Fetch 和 CORS 最有趣的功能就是能够发出知道 HTTP Cookie 和 HTTP 身份验证的 凭证 请求。默认情况下,在跨站点 XMLHttpRequest 或 Fetch 调用中,浏览器将不发送凭据。调用 XMLHttpRequest对象或 Request 构造函数时必须设置一个特定的标志。

    在下面这个例子中,最初从 http://foo.example 加载的内容对设置了 Cookies 的 http://bar.other 上的资源进行了简单的 GET 请求, foo.example 上可能的代码如下

    const invocation = new XMLHttpRequest();
    const url = 'http://bar.other/resources/credentialed-content/';
        
    function callOtherDomain() {
      if (invocation) {
        invocation.open('GET', url, true);
        invocation.withCredentials = true;
        invocation.onreadystatechange = handler;
        invocation.send(); 
      }
    }
    

    第7行显示 XMLHttpRequest 上的标志,必须设置该标志才能使用 Cookie 进行调用。默认情况下,调用是不在使用 Cookie 的情况下进行的。由于这是一个简单的 GET 请求,因此不会进行预检,但是浏览器将拒绝任何没有 Access-Control-Allow-Credentials 的响应:标头为true,指的是响应不会返回 web 页面的内容。

    上面的请求用下图可以表示

    这是客户端和服务器之间的示例交换:

    GET /resources/access-control-with-credentials/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Connection: keep-alive
    Referer: http://foo.example/examples/credential.html
    Origin: http://foo.example
    Cookie: pageAccess=2
    
    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:34:52 GMT
    Server: Apache/2
    Access-Control-Allow-Origin: https://foo.example
    Access-Control-Allow-Credentials: true
    Cache-Control: no-cache
    Pragma: no-cache
    Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
    Vary: Accept-Encoding, Origin
    Content-Encoding: gzip
    Content-Length: 106
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Content-Type: text/plain
    
    
    [text/plain payload]
    

    上面第10行包含指向http://bar.other 上的内容 Cookie,但是如果 bar.other 没有以 Access-Control-Allow-Credentials:true 响应(下面第五行),响应将被忽略,并且不能使用网站返回的内容。

    请求凭证和通配符

    当回应凭证请求时,服务器必须在 Access-Control-Allow-Credentials 中指定一个来源,而不能直接写* 通配符

    因为上面示例代码中的请求标头包含 Cookie 标头,如果 Access-Control-Allow-Credentials 中是指定的通配符 * 的话,请求会失败。

    注意上面示例中的 Set-Cookie 响应标头还设置了另外一个值,如果发生故障,将引发异常(取决于所使用的API)。

    ###HTTP 响应标头

    下面会列出一些服务器跨域共享规范定义的 HTTP 标头,上面简单概述了一下,现在一起来认识一下,主要会介绍下面这些

    • Access-Control-Allow-Origin
    • Access-Control-Allow-Credentials
    • Access-Control-Allow-Headers
    • Access-Control-Allow-Methods
    • Access-Control-Expose-Headers
    • Access-Control-Max-Age
    • Access-Control-Request-Headers
    • Access-Control-Request-Method
    • Origin

    Access-Control-Allow-Origin

    Access-Control-Allow-Origin 是 HTTP 响应标头,指示响应是否能够和给定的源共享资源。Access-Control-Allow-Origin 指定单个资源会告诉浏览器允许指定来源访问资源。对于没有凭据的请求 *通配符,告诉浏览器允许任何源访问资源。

    例如,如果要允许源 https://mozilla.org 的代码访问资源,可以使用如下的指定方式

    Access-Control-Allow-Origin: https://mozilla.org
    Vary: Origin
    

    如果服务器指定单个来源而不是*通配符,则服务器还应在 Vary 响应标头中包含该来源。

    Access-Control-Allow-Credentials

    Access-Control-Allow-Credentials 是 HTTP 的响应标头,这个标头告诉浏览器,当包含凭证请求(Request.credentials)时是否将响应公开给前端 JavaScript 代码。

    这时候你会问到 Request.credentials 是什么玩意?不要着急,来给你看一下,首先来看 Request 是什么玩意,

    实际上,Request 是 Fetch API 的一类接口代表着资源请求。一般创建 Request 对象有两种方式

    • 使用 Request() 构造函数创建一个 Request 对象
    • 还可以通过 FetchEvent.request api 操作来创建

    再来说下 Request.credentials 是什么意思,Request 接口的凭据只读属性指示在跨域请求的情况下,用户代理是否应从其他域发送 cookie。(其他 Request 对象的方法详见 https://developer.mozilla.org/en-US/docs/Web/API/Request)

    当发送的是凭证模式的请求包含 (Request.credentials)时,如果 Access-Control-Allow-Credentials 值为 true,浏览器将仅向前端 JavaScript 代码公开响应。

    Access-Control-Allow-Credentials: true
    

    凭证一般包括 cookie、认证头和 TLS 客户端证书

    当用作对预检请求响应的一部分时,这表明是否可以使用凭据发出实际请求。注意简单的 GET 请求不会进行预检。

    可以参考一个实际的例子 https://www.jianshu.com/p/ea485e5665b3

    Access-Control-Allow-Headers

    Access-Control-Allow-Headers 是一个响应标头,这个标头用来响应预检请求,它发出实际请求时可以使用哪些HTTP标头。

    示例

    • 自定义标头

    这是 Access-Control-Allow-Headers 标头的示例。它表明除了像 CROS 安全列出的请求标头外,对服务器的 CROS 请求还支持名为 X-Custom-Header 的自定义标头。

    Access-Control-Allow-Headers: X-Custom-Header
    
    • 多个标头

    这个例子展示了 Access-Control-Allow-Headers 如何使用多个标头

    Access-Control-Allow-Headers: X-Custom-Header, Upgrade-Insecure-Requests
    
    • 绕过其他限制

    尽管始终允许使用 CORS 安全列出的请求标头,并且通常不需要在 Access-Control-Allow-Headers 中列出这些标头,但是无论如何列出它们都将绕开适用的其他限制。

    Access-Control-Allow-Headers: Accept
    

    这里你可能会有疑问,哪些是 CORS 列出的安全标头?(别嫌累,就是这么麻烦)

    有下面这些 Accep、Accept-Language、Content-Language、Content-Type ,当且仅当包含这些标头时,无需在 CORS 上下文中发送预检请求。

    Access-Control-Allow-Methods

    Access-Control-Allow-Methods 也是响应标头,它指定了哪些访问资源的方法可以使用预检请求。例如

    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Methods: *
    

    Access-Control-Expose-Headers

    Access-Control-Expose-Headers 响应标头表明哪些标头可以作为响应的一部分公开。默认情况下,仅公开6个CORS安全列出的响应标头,分别是

    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma

    如果希望客户端能够访问其他标头,则必须使用 Access-Control-Expose-Headers 标头列出它们。下面是示例

    要公开非 CORS 安全列出的请求标头,可以像如下这样指定

    Access-Control-Expose-Headers: Content-Length
    

    要另外公开自定义标头,例如 X-Kuma-Revision,可以指定多个标头,并用逗号分隔

    Access-Control-Expose-Headers: Content-Length, X-Kuma-Revision
    

    在不是凭证请求中,你还可以使用通配符

    Access-Control-Expose-Headers: *
    

    但是,这不会通配 Authorization 标头,因此如果需要公开它,则需要明确列出

    Access-Control-Expose-Headers: *, Authorization
    

    Access-Control-Max-Age

    Access-Control-Max-Age 响应头表示预检请求的结果可以缓存多长时间,例如

    Access-Control-Max-Age: 600 
    

    表示预检请求可以缓存10分钟

    Access-Control-Request-Headers

    浏览器在发出预检请求时使用 Access-Control-Request-Headers 请求标头,使服务器知道在发出实际请求时客户端可能发送的 HTTP 标头。

    Access-Control-Request-Headers: X-PINGOTHER, Content-Type
    

    ####Access-Control-Request-Method

    同样的,Access-Control-Request-Method 响应标头告诉服务器发出预检请求时将使用那种 HTTP 方法。此标头是必需的,因为预检请求始终是 OPTIONS,并且使用的方法与实际请求不同。

    Access-Control-Request-Method: POST
    

    Origin

    Origin 请求标头表明匹配的来源,它不包含任何信息,仅仅包含服务器名称,它与 CORS 请求以及 POST 请求一起发送,它类似于 Referer 标头,但与此标头不同,它没有公开整个路径。例如

    Origin: https://developer.mozilla.org
    

    HTTP 条件请求

    HTTP 具有条件请求的概念,通过比较资源更新生成的值与验证器的值进行比较,来确定资源是否进行过更新。这样的请求对于验证缓存的内容、条件请求、验证资源的完整性来说非常重要。

    原则

    HTTP 条件请求是根据特定标头的值执行不同的请求,这些标头定义了一个前提条件,如果前提条件匹配或不匹配,则请求的结果将有所不同。

    • 对于 安全 的方法,像是 GET、用于请求文档的资源,仅当条件请求的条件满足时发回文档资源,所以,这种方式可以节约带宽。

    什么是安全的方法,对于 HTTP 来说,安全的方法是不会改变服务器状态的方法,换句话说,如果方法只是只读操作,那么它肯定是安全的方法,比如说 GET 请求,它肯定是安全的方法,因为它只是请求资源。几种常见的方法肯定是安全的,它们是 GET、HEAD和 OPTIONS。所有安全的方法都是幂等的(这他妈幂等又是啥意思?)但不是所有幂等的方法都是安全的,例如 PUT 和 DELETE 都是幂等的,但不安全。

    幂等性:如果相同的客户端发起一次或者多次 HTTP 请求会得到相同的结果,则说明 HTTP 是幂等的。(我们这次不深究幂等性)

    • 对于 非安全 的方法,像是 PUT,只有原始文档与服务器上存储的资源相同时,才可以使用条件请求来传输文档。(PUT 方法通常用来传输文件,就像 FTP 协议的文件上传一样)

    验证

    所有的条件请求都会尝试检查服务器上存储的资源是否与某个特定版本的资源相匹配。为了满足这种情况,条件请求需要指示资源的版本。由于无法和整个文件逐个字符进行比较,因此需要把整个文件描绘成一个值,然后把此值和服务器上的资源进行比较,这种方式称为比较器,比较器有两个条件

    • 文档的最后修改日期
    • 一个不透明的字符串,用于唯一标识每个版本,称为实体标签或 Etag

    比较两个资源是否时相同的版本有些复杂,根据上下文,有两种相等性检查

    • 当期望的是字节对字节进行比较时,例如在恢复下载时,使用强 Etag进行验证
    • 当用户代理需要比较两个资源是否具有相同的内容时,使用若 Etag 进行验证

    HTTP 协议默认使用 强验证,它指定何时进行弱验证

    强验证

    强验证保证的是字节 级别的验证,严格的验证非常严格,可能在服务器级别难以保证,但是它能够保证任何时候都不会丢失数据,但这种验证丢失性能。

    要使用 Last-Modified 很难实现强验证,通常,这是通过使用带有资源的 MD5 哈希值的 Etag 来完成的。

    弱验证

    弱验证不同于强验证,因为如果内容相等,它将认为文档的两个版本相同,例如,一个页面与另一个页面的不同之处仅在于页脚的日期不同,因此该页面被认为与其他页面相同。而使用强验证时则被认为这两个版本是不同的。构建一个若验证的 Etag 系统可能会非常复杂,因为这需要了解每个页面元素的重要性,但是对于优化缓存性能非常有用。

    下面介绍一下 Etag 如何实现强弱验证。

    Etag 响应头是特定版本的标识,它能够使缓存变得更高效并能够节省带宽,因为如果缓存内容未发生变更,Web 服务器则不需要重新发送完整的响应。除此之外,Etag 能够防止资源同时更新互相覆盖。

    如果给定 URL 上的资源发生变更,必须生成一个新的 Etag 值,通过比较它们可以确定资源的两个表示形式是否相同。

    Etag 值有两种,一种是强 Etag,一种是弱 Etag;

    • 强 Etag 值,无论实体发生多么细微的变化都会改变其值,一般的表示如下
    Etag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
    
    • 弱 Etag 值,弱 Etag 值只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变 Etag 值。这时,会在字段值最开始处附加 W/。
    Etag: W/"0815"
    

    下面就来具体探讨一下条件请求的标头和 Etag 的关系

    条件请求

    条件请求主要包含的标头如下

    • If-Match
    • If-None-Match
    • If-Modified-Since
    • If-Unmodified-Since
    • If-Range

    If-Match

    对于 GETPOST 方法,服务器仅在与列出的 Etag(响应标头) 之一匹配时才返回请求的资源。这里又多了一个新词 Etag,我们稍后再说 Etag 的用法。对于像是 PUT 和其他非安全的方法,在这种情况下,它仅仅将上传资源。

    下面是两种常见的案例

    • 对于 GETPOST 方法,会结合使用 Range 标头,它可以确保新发送请求的范围与上一个请求的资源相同,如果不匹配的话,会返回 416 响应。
    • 对于其他方法,特别是 PUT 方法,If-Match 可以防止丢失更新,服务器会比对 If-Match 的字段值和资源的 Etag 值,仅当两者一致时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响应。例如
    If-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"
    If-Match: *
    

    If-None-Match

    条件请求,它与 If-Match 的作用相反,仅当 If-None-Match 的字段值与 Etag 值不一致时,可处理该请求。对于GETHEAD ,仅当服务器没有与给定资源匹配的 Etag 时,服务器将返回 200 OK作为响应。对于其他方法,仅当最终现有资源的 Etag 与列出的任何值都不匹配时,才会处理请求。

    GETPOST 发送的 If-None-MatchEtag 匹配时,服务器会返回 304

    If-None-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"
    If-None-Match: W/"67ab43", "54ed21", "7892dd"
    If-None-Match: *
    

    If-Modified-Since

    If-Modified-Since 是 HTTP 条件请求的一部分,只有在给定日期之后,服务端修改了请求所需要的资源,才会返回 200 OK 的响应。如果在给定日期之后,服务端没有修改内容,响应会返回 304 并且不带任何响应体。If-Modified-Since 只能使用 GETHEAD 请求。

    If-Modified-Since 与 If-None-Match 结合使用时,它将被忽略,除非服务器不支持 If-None-Match。一般表示如下

    If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT 
    

    注意:这是格林威治标准时间。 HTTP 日期始终以格林尼治标准时间表示,而不是本地时间。

    If-Range

    If-Range 也是条件请求,如果满足条件(If-Range 的值和 Etag 值或者更新的日期时间一致),则会发出范围请求,否则将会返回全部资源。它的一般表示如下

    If-Range: Wed, 21 Oct 2015 07:28:00 GMT 
    If-Range: bfc13a64729c4290ef5b2c2730249c88ca92d82d
    

    If-Unmodified-Since

    If-Unmodified-Since HTTP 请求标头也是一个条件请求,服务器只有在给定日期之后没有对其进行修改时,服务器才返回请求资源。如果在指定日期时间后发生了更新,则以状态码 412 Precondition Failed 作为响应返回。

    If-Unmodified-Since: Wed, 21 Oct 2015 07:28:00 GMT 
    

    条件请求示例

    缓存更新

    条件请求最常见的示例就是更新缓存,如果缓存是空或没有缓存,则以200 OK的状态发送回请求的资源。如下图所示

    客户端第一次发送请求没有,缓存为空并且没有条件请求,服务器在收到客户端请求后,设置验证器 Last-ModifiedEtag 标签,并把这两个标签随着响应一起发送回客户端。

    下一次客户端再发送相同的请求后,会直接从缓存中提取,只要缓存没有过期,就不会有任何新的请求到达服务器重新下载资源。但是,一旦缓存过期,客户端不会直接使用缓存的值,而是发出条件请求。 验证器的值用作 If-Modified-SinceIf-Match标头的参数。

    缓存过期后客户端重新发起请求,服务器收到请求后发现如果资源没有更改,服务器会发回 304 Not Modified响应,这使缓存再次刷新,并让客户端使用缓存的资源。 尽管有一个响应/请求往返消耗一些资源,但是这比再次通过有线传输整个资源更有效。

    如果资源已经发生更改,则服务器仅使用新版本的资源返回 200 OK 响应,就像没有条件请求,并且客户端会重新使用新的资源,从这个角度来讲,缓存是条件请求的前置条件

    断点续传

    HTTP 可以支持文件的部分下载,通过保留已获得的信息,此功能允许恢复先前的操作,从而节省带宽和时间。

    支持断点续传的服务器通过发送 Accept-Ranges 标头广播此消息,一旦发生这种情况,客户端可以通过发送缺少范围的 Ranges标头来恢复下载

    这里你可能有疑问 RangesContent-Range是什么,来解释一下

    Range

    Range HTTP 请求标头指示服务器应返回文档指定部分的资源,可以一次请求一个 Range 来返回多个部分,服务器会将这些资源返回各个文档中。如果服务器成功返回,那么将返回 206 响应;如果 Range 范围无效,服务器返回416 Range Not Satisfiable错误;服务器还可以忽略 Range 标头,并且返回 200 作为响应。

    Range: bytes=200-1000, 2000-6576, 19000-
    

    还有一种表示是

    Range: bytes=0-499, -500 
    

    它们分别表示请求前500个字节和最后500个字节,如果范围重叠,则服务器可能会拒绝该请求。

    Content-Range

    HTTP 的 Content-Range 响应标头是针对范围请求而设定的,返回响应时使用首部字段 Content-Range,能够告知客户端响应实体的哪部分是符合客户端请求的,字段以字节为单位。它的一般表示如下

    Content-Range: bytes 200-1000/67589 
    

    上段代码表示从所有 67589 个字节中返回 200-1000 个字节的内容

    那么上面的 Content-Range你也应该知道是什么意思了

    断点续传的原理比较简单,但是这种方式存在潜在的问题:如果在两次下载资源的期间进行了资源更新,那么获得的范围将对应于资源的两个不同版本,并且最终文档将被破坏。

    为了阻止这种情况的出现,就会使用条件请求。对于范围来说,有两种方法可以做到这一点。一种方法是使用 If-Modified-SinceIf-Match,如果前提条件失败,服务器将返回错误;然后客户端从头开始重新下载。

    即使此方法有效,当文档资源发生改变时,它也会添加额外的 响应/请求 交换。这会降低性能,并且 HTTP 具有特定的标头来避免这种情况 If-Range

    该解决方案效率更高,但灵活性稍差一些,因为在这种情况下只能使用一个 Etag。

    通过乐观锁避免丢失更新

    Web 应用程序中最普遍的操作是资源更新。这在任何文件系统或应用程序中都很常见,但是任何允许存储远程资源的应用程序都需要这种机制。

    使用 put 方法,你可以实现这一点,客户端首先读取原始文件对其进行修改,然后把它们发送到服务器。

    上面这种请求响应存在问题,一旦考虑到并发性,事情就会变得不准确。当客户端在本地修改资源打算重新发送之前,第二个客户端可以获取相同的资源并对资源进行修改操作,这样就会造成问题。当它们重新发送请求到服务器时,第一个客户端所做的修改将被第二次客户端的修改所覆盖,因为第二次客户端修改并不知道第一次客户端正在修改。资源提交并更新的一方不会传达给另外一方,所以要保留哪个客户的更改,将随着他们提交的速度而变化; 这取决于客户端,服务器的性能,甚至取决于人工在客户端编辑文档的性能。 例如下面这个流程

    如果没有两个用户同时操作服务器,也就不存在这个问题。但是,现实情况是不可能只有单个用户出现的,所以为了规避或者避免这个问题,我们希望客户端资源在更新时进行提示或者修改被拒绝时收到通知。

    条件请求允许实现乐观锁算法。这个概念是允许所有的客户端获取资源的副本,然后让他们在本地修改资源,并成功通过允许第一个客户端提交更新来控制并发,基于此服务端的后面版本的更新都将被拒绝。

    这是使用 If-MatchIf-Unmodified-Since标头实现的。如果 Etag 与原始文件不匹配,或者自获取以来已对文件进行了修改,则更改为拒绝更新,并显示412 Precondition Failed错误。

    HTTP Cookies

    HTTP 协议中的 Cookie 包括 Web Cookie浏览器 Cookie,它是服务器发送到 Web 浏览器的一小块数据。服务器发送到浏览器的 Cookie,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登录状态。

    HTTP Cookie 机制是 HTTP 协议无状态的一种补充和改良

    Cookie 主要用于下面三个目的

    • 会话管理

    登陆、购物车、游戏得分或者服务器应该记住的其他内容

    • 个性化

    用户偏好、主题或者其他设置

    • 追踪

    记录和分析用户行为

    Cookie 曾经用于一般的客户端存储。虽然这是合法的,因为它们是在客户端上存储数据的唯一方法,但如今建议使用现代存储 API。Cookie 随每个请求一起发送,因此它们可能会降低性能(尤其是对于移动数据连接而言)。客户端存储的现代 API 是 Web 存储 API(localStorage 和 sessionStorage)和 IndexedDB。

    创建 Cookie

    当接收到客户端发出的 HTTP 请求时,服务器可以发送带有响应的 Set-Cookie 标头,Cookie 通常由浏览器存储,然后将 Cookie 与 HTTP 标头一同向服务器发出请求。可以指定到期日期或持续时间,之后将不再发送Cookie。此外,可以设置对特定域和路径的限制,从而限制 cookie 的发送位置。

    Set-Cookie 和 Cookie 标头

    Set-Cookie HTTP 响应标头将 cookie 从服务器发送到用户代理。下面是一个发送 Cookie 的例子

    HTTP/2.0 200 OK
    Content-type: text/html
    Set-Cookie: yummy_cookie=choco
    Set-Cookie: tasty_cookie=strawberry
    
    [page content]
    

    此标头告诉客户端存储 Cookie

    现在,随着对服务器的每个新请求,浏览器将使用 Cookie 头将所有以前存储的 cookie 发送回服务器。

    GET /sample_page.html HTTP/2.0
    Host: www.example.org
    Cookie: yummy_cookie=choco; tasty_cookie=strawberry
    

    Cookie 主要分为三类,它们是 会话Cookie永久CookieCookie的 Secure 和 HttpOnly 标记,下面依次来介绍一下

    会话 Cookies

    上面的示例创建的是会话 Cookie ,会话 Cookie 有个特征,客户端关闭时 Cookie 会删除,因为它没有指定Expires 或 Max-Age 指令。 这两个指令你看到这里应该比较熟悉了。

    但是,Web 浏览器可能会使用会话还原,这会使大多数会话 Cookie 保持永久状态,就像从未关闭过浏览器一样

    永久性 Cookies

    永久性 Cookie 不会在客户端关闭时过期,而是在特定日期(Expires)或特定时间长度(Max-Age)外过期。例如

    Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
    

    Cookie的 Secure 和 HttpOnly 标记

    安全的 Cookie 需要经过 HTTPS 协议通过加密的方式发送到服务器。即使是安全的,也不应该将敏感信息存储在cookie 中,因为它们本质上是不安全的,并且此标志不能提供真正的保护。

    HttpOnly 的作用

    • 会话 cookie 中缺少 HttpOnly 属性会导致攻击者可以通过程序(JS脚本、Applet等)获取到用户的 cookie 信息,造成用户cookie 信息泄露,增加攻击者的跨站脚本攻击威胁。

    • HttpOnly 是微软对 cookie 做的扩展,该值指定 cookie 是否可通过客户端脚本访问。

    • 如果在 Cookie 中没有设置 HttpOnly 属性为 true,可能导致 Cookie 被窃取。窃取的 Cookie 可以包含标识站点用户的敏感信息,如 ASP.NET 会话 ID 或 Forms 身份验证票证,攻击者可以重播窃取的 Cookie,以便伪装成用户或获取敏感信息,进行跨站脚本攻击等。

    Cookie 的作用域

    DomainPath 标识定义了 Cookie 的作用域:即 Cookie 应该发送给哪些 URL。

    Domain 标识指定了哪些主机可以接受 Cookie。如果不指定,默认为当前主机(不包含子域名)。如果指定了Domain,则一般包含子域名。

    例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如developer.mozilla.org)。

    例如,设置 Path=/docs,则以下地址都会匹配:

    • /docs
    • /docs/Web/
    • /docs/Web/HTTP

    文章参考:

    https://developer.mozilla.org/en-US/docs/

    https://www.jianshu.com/p/5c41c536d47f

    https://www.w3schools.com/php/default.asp

    https://www.jianshu.com/p/ea485e5665b3

    https://blog.csdn.net/qq_38098125/article/details/101213336

    展开全文
  • 黑科技

    千次阅读 2017-07-21 15:46:53
    最前沿的科技会给人类生活带来哪些改变?它们的原理又是什么?  依靠克隆、干细胞等技术,人类可以修复受损的身体,开展器官移植;通过对长寿基因的研究,人们可以延年益寿;外骨骼能让人成为钢铁侠,而探测雷达能...
    border="0" width="330" height="86" src="//music.163.com/outchain/player?type=3&id=908142315&auto=0&height=66"> 
    

    【 随着医学领域的发展,人类活到一二百岁,甚至更长,并非遥不可及。】
           未来的世界什么样?最前沿的科技会给人类生活带来哪些改变?它们的原理又是什么?
           依靠克隆、干细胞等技术,人类可以修复受损的身体,开展器官移植;通过对长寿基因的研究,人们可以延年益寿;外骨骼能让人成为钢铁侠,而探测雷达能让你拥有 “火眼金睛”;机器的深度学习与 “天罗地网” 的结合,让人与世界以更奇妙的方式连接…… 未来的生活,将使科幻大片成为现实。
           本期音频取材于 15 位技术大咖的最新研究成果,从医疗水平的改善、人体机能的延展、信息网络沟通三个方面,详细解说众多前沿科技带给人类生活的改变。用 22 分钟的时间,为你展现前沿科技成果,带你走进未来世界。

    你将听到:
    1. 如何利用干细胞培植方式解决器官再生问题?
    2. 延年益寿的 “不老仙丹” 是否真的存在?
    3. 未来科技怎样让你力大无穷又 “火眼金睛”?
    4. 人工智能 AlphaGo 为什么那么聪明?

    书籍信息:

    这里写图片描述
    书名:《黑科技》
    副标题:21 项前沿科技将如何创造未来
    作者:顾志强等
    出版社:中国友谊出版公司
    出版年:2017-3
    页数:380
    定价:58.00 元
    装帧:平装
    ISBN:9787505737525

    关于作者

           本书由 15 位作者联袂写成,其中包括了亚马逊软件工程师、苹果 “下一代输入技术” 硬件工程师、哈佛大学遗传和分子生物学博士等等。诸位作者专业各有差异,均毕业于名校并在一线科技公司工作,既有扎实的理论功底,又有最前沿技术的实践经验。

    关于本书

           本书涉及了前沿科技领域和科技产品,包括热门的人工智能、虚拟现实等科技的原理和进展。在例举产品的同时,作者详细分析了相关技术和作用机理,并对科技改变生活的未来图景做了前瞻性展望。

    核心内容

           从提高医疗水平、延展人的身体机能、增强人与外界信息沟通等三个方面,详细解析黑科技对未来生活的众多改变。
    这里写图片描述
    点击查看大图,保存到手机,也可以分享到朋友圈

    一、黑科技与医疗发展
    1. 器官移植
           人类健康面对的一大难题,就是器官的病变。一旦器官衰竭或受损,就要靠器官移植来延续生命,但合适器官的供给量非常低。曾有科学家尝试把动物器官移植到人身上,发现不同物种之间有严重的排异反应。也有科学家试图用新材料来制造人工机械器官,希望像制造假肢一样制造内脏,但自然器官的很多功能很难通过机械实现。
           日本生物医学科学家、京都大学细胞研究所所长山中伸弥带领的团队,通过导入特定基因的方式,成功地将人类的皮肤细胞变成胚胎干细胞。胚胎干细胞是一种 “种子” 细胞,给它一些合适的条件或者刺激因素,这种细胞就可以变成人类所需要的某种特定细胞。人们可以从实验室中得到任何一种想要的细胞,用于器官移植治疗了。
           造出 “种子” 细胞,是器官再生的第一步,用于临床的人体组织和器官移植,是下一个需要解决的问题。不同的器官有不同的方法。日本科学家笹井芳树领导的科研团队,把胚胎干细胞培养成了视网膜的初始结构,已经进入临床手术,具体的效果还有待观察。如果成功,将是医学上的重大进步。
    2. 延长寿命
           科学家经过对一系列生物观察发现:少吃有利于长寿。节食对生物体而言,实际上意味着一种压力,而一定程度的压力,能够刺激机体产生防御性反应,增强抵抗不利环境和疾病的能力,从而达到延年益寿的作用。
           科学家们发现,多吃葡萄皮有可能延长寿命。人体中有一种特殊的蛋白质,是维持人体机能年轻态的关键。哈佛大学研究队伍发现,白藜芦醇能够增强长寿蛋白质的生物活性,延长人的寿命,而葡萄皮中正含有丰富的白藜芦醇。

    二、黑科技与人体机能
    1. 机器人外骨骼
           体外骨骼装置属于机器人的范畴,它能够为穿戴者提供助力,不仅能应用于军事战争,还被广泛地用于医疗、救援和工程作业等方面。机器人外骨骼一般包括了机械结构、传感、动力传动、能源和控制等部分。虽然日常生活中见到的不多,但各国已经有不少相对成熟的产品。
           日本开发的体外骨骼,专门针对残障人士和助力强体力作业开发。工作原理:当人产生意念想要做出动作时,脑部会产生控制信号,并通过神经传递到皮肤,形成表面肌电信号,这套体外骨骼就是通过检测、采集这些信号,控制机械结构来做出类似于人的动作。
           美国开发的 “下肢外骨骼”,是目前在军事应用方面最领先的外骨骼系统,能大幅度提高负重能力。外骨骼采用液压驱动,以燃油为能源,动力强劲。当人腿开始产生动作的时候,装在外骨骼的传感器就会感知到力的运动趋势,并驱动外骨骼顺应这个趋势,从而增强力量。
    2. 迷你雷达
           雷达的原理:用发射无线电磁波得到的反射波来探测目标物体。随着天线尺寸和芯片的日益缩小,雷达设备也变成了小巧玲珑的探测器,可以应用到更多领域,用于穿戴式设备,可以让人 “看” 到很多不易察觉的信息。
           雷达还能让人通过虚空的手指动作来控制电脑。谷歌推出了一款迷你雷达,能够嵌入设备,捕捉手指的细微动作,让人隔空通过手势来控制触屏。
    3. 磁悬浮滑板
           美国的一家公司造出了磁悬浮滑板,能载着人在金属地面上悬浮、行走。它的原理是利用磁铁磁极相斥而产生的力,把人托起来。

    三、黑科技与沟通模式
    1. 人与机器的沟通
           人想要让机器做更多的事情,需要机器 “学会” 学习。让机器拥有智能,最关键的一点,在于让它能进行深度学习,也就是让机器能够像人一样学习,从而变得更加智能,更好地为人类服务。
           1958 年,美国科学家发明了一种拥有学习和认知功能的计算机,模拟人大脑机能中的神经和它们发挥作用的方式,能够识别简单的字母图片。
    如果不断增加神经网络的层次,把各个层次连接起来,可以创造出功能强大的多层神经网络。
    2. 网络基础设施
           未来的宽带网络,必然更快、更便宜、流量更大。现在用的宽带网络,是在地面铺设的,属于 “地网”,主干线都是在地球表面。未来要打造的是 “天网”,把网络的主干线铺到天上去。
    【案例】
    Facebook 不久前进行了太阳能无人机的试飞。这个无人机是专门提供互联网接入服务的。Facebook 计划在全球布局上万架这样的无人机,都使用激光通信技术。这种技术的传输速率能够达到 10Gbps,接近地面光纤水平。它们的目标是通过使用激光、无人机等网络通讯的新方法,把互联网连接数量增加 10 倍,把上网价格降低到目前的十分之一。
           谷歌也正在进行着类似计划,它也是用无人机做平台,但采用的技术是毫米波通讯技术,这种技术比 4G 的传输速度快 40 倍。
           除此之外,谷歌、Facebook 这种巨头还有更高的目标,那就是利用卫星构建智能宽带网络。在理想状态下,“天网”和 “地网” 融为一体、多种类型的网络混合、各种设备自带热点组成的局域网络,将会把所有设备联系起来,成为未来最广泛的应用形态。人与人、人与物体的连接,会在这样的趋势中越来越方便快捷。

    本书金句

    1. 人体的细胞有很多种,不同的器官需要不同的细胞。想要制造器官,首先就得有合适的细胞。

    2. 随着黑科技在医学领域的发展,未来的人活到一二百岁,甚至更长,并非遥不可及。

    3. 突破地心引力的可能性一旦具备,就已经是革命性的突破。再往后的发展,要做的只是怎样让这种悬浮飞行更加稳定、续航时间更长。

    4. 人是社会性生物,在精神层面需要与外界沟通,才能让生活更加充实、生命更加完满

    5. 由深度学习发展而来的人工智能产品,正带着我们走进更舒适的生活。

    展开全文
  • 一文带你秒懂5G黑科技

    千次阅读 2019-08-12 17:31:00
    通信技术,无论什么黑科技白科技,只分两种——有线通信和无线通信 我和你打电话,信息数据要么在空中传播(看不见、摸不着),要么在实物上传播(看得见、摸得着)。 。 。 在有线介质上传播数据,想要高速很容易。...

    点击上方“朱小厮的博客”,选择“设为星标

    回复”1024“获取独家整理的学习资料


    640



    说到5G,就要从一个“神奇的公式”说起。



       一个神奇的公式。    


    就是这个公式。


    640?wx_fmt=jpeg


    如果知道这个公式的童鞋,请骄傲地为自己鼓个掌。


    640?wx_fmt=jpeg


    如果不记得,或是看不懂,也没关系,我再解释一下。


    640?wx_fmt=png


    就是这个超简单的公式,蕴含了我们无线通信技术的博大精深。


    无论是往事随风的1G、2G、3G,还是意气风发的4G、5G,说来说去,都是在这个数学公式上做文章。


    且听我慢慢道来。



        有线? 无线? ……  



    通信技术,无论什么黑科技白科技,只分两种——有线通信和无线通信


    我和你打电话,信息数据要么在空中传播(看不见、摸不着),要么在实物上传播(看得见、摸得着)。


    640?wx_fmt=png


    在有线介质上传播数据,想要高速很容易。 


    实验室中,单条光纤最大速度已达到了26Tbps。是传统网线的两万六千倍。


    640?wx_fmt=jpeg


    空中传播这部分,才是移动通信的瓶颈所在。


    640?wx_fmt=png


    所以,5G重点是研究无线这部分的瓶颈突破。



      好大一个波。  



    大家都知道,电波和光波都属于电磁波。


    电磁波的频率资源有限,根据不同的频率特性,有不同的用途。


    640?wx_fmt=png


    我们目前主要使用电波进行通信。


    当然,光波通信也在崛起,例如可见光通信LiFi(LightFidelity)


    ▼图片来自网络

    640?wx_fmt=jpeg


    不偏题,回到电波先。


    电波属于电磁波的一种,它的频率资源也是有限的。


    为了避免干扰和冲突,我们在电波这条公路上进一步划分车道,分配给不同的对象和用途。

     

    ▼不同频率电波的用途

    640?wx_fmt=png


    大家注意上面图中的红色字体。一直以来,我们主要是用中频~超高频进行手机通信的。


    例如经常说的“GSM900”、“CDMA800”,其实就是工作频段900MHz和800MHz的意思。


    目前主流的4G LTE,属于超高频和特高频。


    我们国家主要使用超高频:


    640?wx_fmt=jpeg


    随着1G、2G、3G、4G的发展,使用的频率是越来越高的。


    为什么呢?


    因为频率越高,速度越快。


    又为什么呢? 


    因为频率越高,车道(频段)越宽。 


    640?wx_fmt=png


    看懂了吧。车道按指数级扩大。


    640?wx_fmt=png


    更高的频率→更大的带宽→更快的速度


    640?wx_fmt=png


    5G的频段具体是多少呢?


    上个月,我们国家工信部下发通知,明确了我国的5G初始中频频段

    3.3-3.6GHz、4.8-5GHz两个频段


    同时,24.75-27.5GHz、37-42.5GHz高频频段正在征集意见。


    目前,国际上主要使用28GHz进行试验(这个频段也有可能成为5G最先商用的频段)。


    如果按28GHz来算,根据前文我们提到的公式:


    640?wx_fmt=png


    好啦,这个就是5G的第一个技术特点—— 



    毫米波



    继续,继续。


    既然,频率高这么好,你一定会问:“为什么以前我们不用高频率呢?


    原因很简单——不是不想用。是用不起。


    电磁波的一个显著特点:频率越高(波长越短),就越趋近于直线传播(绕射能力越差)。。。


    而且,频率越高,传播过程中的衰减也越大。。。


    你看激光笔(波长635nm左右),射出的光是直的吧,挡住了就过不去了。


    再看卫星通信和GPS导航(波长1cm左右),如果有遮挡物,就没信号了吧。


    而且,卫星那口大锅,必须校准瞄着卫星的方向。稍微歪一点,都会有影响。


    640?wx_fmt=png

    如果5G用高频段,那么它最大的问题,就是覆盖能力会大幅减弱。


    覆盖同一个区域,需要的基站数量将大大超过4G。


    640?wx_fmt=png


    这就是为什么这些年,电信、移动、联通为了低频段而争得头破血流。


    基站就是要花钱买的啊。能不玩命争取么。


    有的频段甚至被称为——黄金频段


    640?wx_fmt=jpeg


    这也是为什么5G时代,运营商拼命怼设备商。


    甚至威胁要自己研发通信设备。


    640?wx_fmt=jpeg

    640?wx_fmt=jpeg


    所以,基于以上原因。


    在高频率的前提下,为了减轻覆盖方面的成本压力,5G必须寻找新的出路。


    首先,是微基站。 



    微基站



    基站有两种,微基站和宏基站。看名字就知道,微基站很小,宏基站很大!


    以前都是大的基站,建一个覆盖一大片 ▼


    640?wx_fmt=jpeg


    以后更多的将是微基站,到处都装,随处可见。


    ▼微基站 看上去是不是很酷炫?

    640?wx_fmt=jpeg


    微基站的造型有很多种,灵活地与周围的环境相融合(伪装),不会让用户在心理上产生不适。


    而且,恰好相反,其实基站数量越多,辐射反而越小! 


    你想一下,冬天,一群人的房子里,一个大功率取暖器好,还是几个小功率取暖器好?


    大功率方案▼

    640?wx_fmt=png


    小功率方案▼

    640?wx_fmt=png


    基站越小巧,数量越多,覆盖就越好,速度就越快。




     天线去哪了?  




    大家有没有发现,以前大哥大都有很长的天线,早期的手机也有突出来的小天线,为什么后来我们就看不到带天线的手机了?

    640?wx_fmt=png

    有人说,是因为信号好了,不需要天线了。


    其实不对。信号再好,也不能没有天线。


    更主要的原因是——天线变小了。


    根据天线特性,天线长度应与波长成正比,大约在1/10~1/4之间。


    640?wx_fmt=png

    频率越高,波长越短,天线也就跟着变短啦! 


    毫米波,天线也变成毫米级。


    这就意味着,天线完全可以塞进手机的里面,甚至可以塞很多根。


    这就是5G的第三大杀手锏—— 



    Massive MIMO



    MIMO就是“多进多出”(Multiple-Input Multiple-Output),多根天线发送,多根天线接收。


    在LTE时代就已经有MIMO了,5G继续发扬光大,变成了加强版的Massive MIMO(Massive:大规模的,大量的)。


    640?wx_fmt=png


    手机都能塞好多根,基站就更不用说了。


    ▼以前的基站,天线就那么几根。


    640?wx_fmt=png


    5G时代,就不是按根来算了,是按“阵”。“天线阵列”。


    ▼天线多得排成阵了。一眼看去一大片的节奏。


    640?wx_fmt=jpeg


    不过,天线之间的距离也不能太近。


    因为天线特性要求,多天线阵列要求天线之间的距离保持在半个波长以上。


    不要问我为什么,去问科学家。




    你是直的? 还是弯的?




    大家都见过灯泡发光吧? 


    其实,基站发射信号的时候,就有点像灯泡发光。


    信号是向四周发射的,对于光,当然是照亮整个房间,如果只是想照亮某个区域或物体,那么,大部分的光都浪费了。


    640?wx_fmt=png


    基站也是一样,大量的能量和资源都浪费了。 


    我们能不能找到一只无形的手,把散开的光束缚起来呢? 


    这样既节约了能量,也保证了要照亮的区域有足够的光。


    答案是:可以。


    这就是——



    波束赋形


    波束赋形

    在基站上布设天线阵列,通过对射频信号相位的控制,使得相互作用后的电磁波的波瓣变得非常狭窄,并指向它所提供服务的手机,而且能跟据手机的移动而转变方向。

    这种空间复用技术,由全向的信号覆盖变为了精准指向性服务,波束之间不会干扰,在相同的空间中提供更多的通信链路,极大地提高基站的服务容量。



    640?wx_fmt=png

    直的都能掰成弯的。还有什么是通信砖家干不出来的?


    640?wx_fmt=png




    别收我钱,行不行?




    在目前的通信网络中,即使是两个人面对面拨打对方的手机(或手机对传照片),信号都是通过基站进行中转的,包括控制信令和数据包。 


    而在5G时代,这种情况就不一定了。


    5G的第五大特点——D2D,也就是Device to Device。



    D2D



    5G时代,同一基站下的两个用户,如果互相进行通信,他们的数据将不再通过基站转发,而是直接手机到手机。


    640?wx_fmt=png


    这样,就节约了大量的空中资源,也减轻了基站的压力。 


    不过,如果你觉得这样就不用付钱,那你就图样图森破了。


    640?wx_fmt=jpeg


    控制消息还是要从基站走的,而且用着频谱资源,运营商爸爸怎么可能放过你。



    后记。



    写着写着,我发现洋洋洒洒写的有点多。


    能看到这的,都是真爱。

    640?wx_fmt=jpeg

    相信大家通过本文对5G和她背后的通信知识已经有了深刻理解,而这一切,都只是源于一个如今小学生都能看懂的数学公式。


    通信技术并不神秘,5G作为通信技术皇冠上最耀眼的宝石,也不是什么遥不可及的创新革命技术,它更多是对现有通信技术的演进。


    正如一位高人所说——



    640?wx_fmt=png

    通信技术的极限,并不是技术工艺方面的限制,而是建立在严谨数学基础上的推论,在可以遇见的未来是基本不可能突破的。




    如何在科学原理的范畴内,进一步发掘通信的潜力,是通信行业众多奋斗者们孜孜不倦的追求。


    就到这里吧,谢谢大家的支持,再见!


    觉得本文好的话,请记得转发哟!




    想知道更多?描下面的二维码关注我

    640?wx_fmt=png

    相关推荐:


    加技术群入口(备注:技术):>>>Learn More<<

    免费资料入口(备注:1024):>>>Learn More<<

    免费星球入口:>>>Free<<<

     
    点个"在看"呗^_^
    展开全文
  • 如果说,贫穷限制了我们的想象,那么东芝的各种黑科技,简直肩负起了撬开我们脑洞的重任啊! 你敢相信空调装置中的循环水也能发电吗?你敢相信6分钟就能给电动汽车充电完毕吗?你...
  • ssprintf,sscanf两个黑科技作用

    千次阅读 2016-04-11 23:05:35
    ssprintf,sscanf两个黑科技作用 关于这2个函数的使用方法网上一搜一大把,可我却还没有发现有好的文章来介绍它们在写题时的神奇用法。这里我也不做过多介绍,就讲一讲它们真正需要用到它们的地方。 int a=...
  • 但实际上,Win10 真的有很多独门秘籍,这些功能大家可能平时并没有注意到,但其实它们独步天下,堪称黑科技!今天,就来给大家介绍一二。 Edge 语音朗读 Win10 20H2 的一大更新,就在于 Edge 浏览
  • 2017黑科技趋势最具看点的十大新品

    千次阅读 2017-09-20 10:46:21
    腾讯数码讯(Human)作为一年一度的全球消费电子市场风向标,今年同样在拉斯维加斯举办的CES 2017消费电子展,依然吸引了一大批全球各个领域的厂商参展,从科技巨头到初创小团队、从传统汽车厂商再到家电企业,似乎...
  • 10 款超级实用的Chrome 黑科技插件

    万次阅读 多人点赞 2018-01-19 17:12:49
    截图方法一:浏览网页时,把鼠标停留在你喜欢的图片上,点击右键,选择“采集到花瓣”(此方法不起作用时,推荐方法一) 同时附带了网页截图功能,提供了选择区域截图、可视区域截图、整张网页截图三个功能,还在...
  • 作者:字节移动技术 —— 谢俊逸苹果升级 14.2,全球 iOS 遭了秧。libffi 在 iOS14.2 上发生了 crash, 我司的许多 App 深受困扰,有许多基础库都是用了 li...
  • 我是架构精进之路,点击上方“关注”,坚持每天为你分享技术干货,私信我回复“01”,送你一份程序员成长进阶大礼包。‍2021牛年春晚的舞台效果太美了,在视觉表现、科技创新上做了诸多尝试,...
  • 唯一一种能走路的:“黑科技”。,曝诈网

    千次阅读 热门讨论 2019-03-18 15:59:09
    所谓黑科技的含义, 就是现实中看起来不可能的存在的科技。(曝诈网) 黑科技无科学依据,但很厉害又挂着科技名义,用起来和魔法一样的东西。 它像玩游戏的外挂一样,它像科幻片一样丰富,它和谍战片一样精彩。对,...
  • 全世界只有3.14 %的人关注了数据与算法之美人工智能的飞速发展,让“黑科技”一词深入人心。目不暇接的各种前沿技术,一再刷新人们的认知世界。所谓“黑科技”,不仅仅要够炫...
  • Android黑科技 自动点击

    千次阅读 2020-03-26 15:28:44
    Android 模拟点击功能
  • Angular黑科技之transclude

    千次阅读 2015-11-15 13:45:54
    Angular黑科技之transclude原文写于 2015-01-28 https://github.com/kuitos/kuitos.github.io/issues/17tansclude是angular生造的一个单词,不要去google啥意思相信我查不出来的。。。至于tranclude怎么翻译这件事我...
  • 来源:AI前线本文约2019字,建议阅读5分钟。本文为你揭秘B 站推出的一种“不挡脸”的黑科技弹幕以及背后的故事。[ 导读 ]不久前,B 站发布一条官方消息,为了更好的提...
  • 五款高效率黑科技神器工具,炸裂好用,省时间

    万次阅读 多人点赞 2019-10-20 16:30:54
    通用手势可以作用于系统中的每一款软件,适用于大多数常见操作,用户可以直接使用(也可以自行进行个性修改)。比如在日常操作中我们经常要执行关闭窗口的操作,但是默认使用触摸板需要费力将鼠标移动到右上角的关闭...
  • 黑科技】转义字符\e

    千次阅读 2016-02-06 12:09:46
    黑科技】转义字符\eWindows 平台下,conio.h 中有许多操作控制台颜色、格式的函数。但是再 Linux 平台下却没有类似的函数。经过在网上的一番搜索,找到了解决此问题的方法——转义字符\e。 注意,\e这种写法可能...
  • 从开始的原生优化,到后面黑科技的外接纹理;从内存占用,到包大小;文本会逐一介绍。希望其中的优化思路和手段,能给大家带去一些启发。 原生模式 从技术层面看图片加载,其实简单来说,追求的是无非是加载的效率的...
  • 你好,欢迎走进本期AI黑科技栏目。请问最近工作顺利吗?家庭幸福吗?生活美满吗?宏碁刚发布的智能佛珠要不要了解一下?是的,你没走错片场,作为老牌电脑厂商的宏碁(ACER),的确发布了这样一款产品——主打智能...
  • PC,安卓的部分浏览器都可以(老大没说要兼容所有浏览器只要部分浏览器能看就可以),测试了好多浏览器有的能关闭窗口不能接受RTMP的推流,...后来想出一个黑科技b.html代码window.open('a.html');a.html代码点击按...
  • 本篇强烈呼吁大家不要去做哪些违反用户体验的黑科技功能,研究研究玩玩就好了啦。全当增长技术,在真实的项目开发中尽量能不用就不要用得好。道理大家都懂的。 目录 那些年Android黑科技①:只要活着,就...
  • 黑科技之机器人外骨骼

    千次阅读 2018-01-07 21:46:58
    内容主题取自《黑科技》,书由硅谷15位技术咖编写。本文主要概述已有落地产品的人体增强领域,旨在抛开繁杂云雾,让读者真切的了解当前科技的真正技术实力。 本文涵盖机器人外骨骼的简单介绍、各国代表性产品的介绍...
  • 黑科技解读:带你秒懂5G技术!

    千次阅读 多人点赞 2018-01-20 12:04:56
    http://www.qianjia.com/html/2017-12/26_281554.html 一切,要从一个“神奇的公式”说起。...通信技术,无论什么黑科技白科技,只分两种——有线通信和无线通信 我和你打电话,信息数据要么在空中传播
  • 爬虫黑科技-绕开百度人机验证

    千次阅读 2018-11-20 07:33:13
    在“爬虫的攻守之道(一)”中你可能已经了解到了无头浏览器的作用以及使用的方法,那么本篇文章就让我们一起用无头浏览器做点事情。   是的你没有看错,我们要“搞”的对象就是百度指数这个网站,不知道你平时...
  • 盘点2017 CES展会所有亮眼黑科技 (下)

    千次阅读 2017-01-21 10:13:29
    文章转自“ittbank”微信公众号,上篇接盘点2017 CES展会所有亮眼黑科技 (上),此篇为下篇,主要展示VR/AR/MR,智慧家庭,显示技术,无人机,音箱,便携产品,传感器,3D打印,人工智能,滑板自行车等领域的黑科技...
  • 目的研究在发酵过程中添加麸皮和曲,对玉米醋减肥和降血脂作用的影响,为玉米资源的开发利用及玉米醋功能性的开发研究提供理论依据。方法 利用营养饲料建立小鼠营养肥胖模型和高血脂模型,设普通对照组、营养对照...
  • 揭秘360手机助手未经用户同意,自动开启辅助功能的“黑科技” Venscor2016-12-01共151843人围观 ,发现 31 个不明物体专题终端安全 *本文原创作者:Venscor,本文属FreeBuf原创奖励计划,未经许可禁止...
  • 契机:今天升级了Android7.1 beta版。然而升上去之后,国产App简直丑态百出啊,给各位看看我的手机截图 啧啧,原来Android7.0以及以下干干净净的通知栏瞬间被这几个家伙占满。有句话说:潮水退去,才知道谁在裸泳啊...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,245
精华内容 8,498
关键字:

黑科技的作用