经典计算机网络知识点
经典计算机网络知识点
- 详细介绍一下TCP的三次握手机制,为什么需要三次握手
- 什么是SYN超时,洪泛攻击,有什么解决策略
- 详细介绍一下TCP的四次挥手机制,为何会有TIME_WAIT状态,为何断开连接需要四次握手,服务器出现大量CLOSE_WAIT状态如何解决
- TCP的滑动窗口机制
- HTTP 与 HTTPS 的区别
- HTTPS加密原理
- 怎样让每个client与server之间采用不同加密方式?
- 如何对协商过程进行加密?
- 客户端怎么获得公钥?
- 引入第三方验证机构解决
- 简要谈一下TCP和UDP的异同点
- 在地址栏键入URL后,发生了什么过程
- 前奏阶段:获取本机IP地址,DNS服务器IP,网关路由器IP和MAC地址
- 第一步:获取域名的IP
- 第二步:建立TCP连接
- 第三步:进行数据交互
- HTTP常见状态码及含义
- Get请求和Post请求区别
- 什么是Cookie和Session,Cookie一般如何使用,有哪些实现Session的机制,两者的区别
详细介绍一下TCP的三次握手机制,为什么需要三次握手
TCP报文段中有两个重要的字段:序号字段(seq)和确认号字段(ack),这两个字段在握手阶段和传输信息过程中起到至关重要的作用。
ACK、SYN表示标志位,其值为1或0;seq代表报文段的序号,ack代表期望收到的下一个报文段的序号。
- 第一次握手:客户端client的TCP会首先向服务端server的TCP发送一个不携带额外数据的特殊TCP报文段,该报文段的SYN(Synchronize Sequence Numbers)标志位会被置为1(表示请求建立连接,这是连接请求报文),故该报文段被称为SYN报文段。此时客户端会随机选取一个初始序列号(client_x),并把该编号放置在序号字段seq中,最后将报文段封装成IP数据包通过层层传递发送给server。
- 第二次握手:server端接收到SYN报文段后,会为该TCP分配缓存和变量,并发送同意连接的SYN-ACK报文段。在该报文段中,SYN标志位仍被置为1,ACK标志位被置为1(表示同意确认建立连接,这是连接接受报文),而确认号字段ack则会放置client_x+1的值,然后服务端也会随机生成一个server_y编号存放到该报文段的序号字段seq中,最后将该报文段封装成IP数据包回传给client。
- 第三次握手:client端接收到SYN-ACK报文段后,知道了server端能够正常接收自己发送的数据,还需要让服务端知晓自己也能够正常接收其发送的数据,故最后也需向server端发送一个ACK报文段。该报文段中,SYN标志位被置为0(表示握手完成),ACK标志位为1,确认号字段ack放置server_y+1的值,序号字段seq则存放client_x+1,且该报文段可以携带数据。
一旦完成上述三个步骤,则表示客户端和服务器进入了ESTABLISHED(TCP连接成功)状态,完成三次握手,可以互相发送携带数据的报文。
三次握手恰好,两次的话server端不知道client端是否能正常接收,四次的话就多余了。
什么是SYN超时,洪泛攻击,有什么解决策略
- 由于在TCP连接的第一次握手中,client会向server端发送SYN报文段,server端收到后为该TCP初始化连续变量和分配缓存,然后server端会回发SYN-ACK报文段响应,并等待来自client端的ACK报文段;若client不完成第三次握手,由于TCP的可靠性,服务器会在终止半开连接并在SYN-RECV队列中移除该TCP之前等待相当长一段时间,这就给经典的DoS攻击,也就是SYN洪泛攻击提供了场景。只要恶意攻击者向服务器发送大量的SYN报文段,而不完成第三次握手,或在SYN报文段里通过欺骗源IP地址,让服务器响应SYN-ACK报文段到假的IP,从而永远收不到ACK,此时大量的SYN报文段接踵而至,会使得server端不断为这些半开连接分配资源,最终耗尽服务器资源,导致内存溢出无法服务。
常见解决方案,采用SYN cookie机制:
- 当server接收到一个SYN报文段时,因为他不清楚这个是合法的连接请求还是恶意攻击,故不会直接为该TCP分配资源,仅打开一个半开的套接字维持连接。然后服务器会根据接收到的SYN报文段中的源IP、目的IP,端口号以及只有自己知道的秘密数,通过复杂散列函数生成一个cookie,然后将该cookie作为序号字段的值响应给client(服务器并不记忆该cookie或任何对应于SYN的其他状态信息)
- 若client是正常合法用户连接,将会返回确认号字段为cookie+1的报文段,server端收到ACK后,会再根据ACK报文段的源IP、目的IP,端口号和秘密数通过散列函数计算出结果,然后判断结果值加1是否等于确认号字段的值,若相等则证明是刚刚请求连接的合法客户端,然后才为该TCP分配资源。(若收不到ACK,或判断不对,则不会分配,避免了恶意攻击)
详细介绍一下TCP的四次挥手机制,为何会有TIME_WAIT状态,为何断开连接需要四次握手,服务器出现大量CLOSE_WAIT状态如何解决
- 首先TCP全双工连接,双方都可以发起关闭连接的请求,每个方向都必须单独进行关闭操作。以client端先发起关闭连接请求为例:当client完成其数据发送任务后就可以发送一个携带FIN标志位的报文段来关闭这个方向的连接,该FIN标志位被置为1。(和SYN相同,FIN也会占用一个序号字段)server端收到FIN只能表明在到接收方的这个方向上没有数据传输,一个TCP连接在收到一个FIN后仍能发送数据,因而服务器会响应客户端一个确认报文(为收到的序号字段+1),并发送FIN标志位为1的终止报文来关闭他这个方向上的连接,最后客户端响应对应的确认报文,服务器收到ACK报文后立即断开连接,客户端等待一段时间后也断开连接。
先发起关闭的一方执行主动关闭,另一方执行被动关闭,简写如下:(先关读,后关写)
- server读通道关闭
- client写通道关闭
- client读通道关闭
- server写通道关闭
详细过程如下:
- Client调用close(),给Server发送FIN报文段,序号为i,请求关闭连接;Server收到FIN后,返回Client确认ACK,序号为i+1,同时关闭Server读通道,即不能再从这个连接上读取东西,现在read()返回0。此时Server的TCP状态转化为CLOSE_WAIT状态。
- Client收到ACK后,关闭Client写通道,不再向连接中写入任何数据。
- Server调用close()关闭连接,给Client发送FIN报文,序号为j;Client收到FIN后,回复Server确认ACK,序号为j+1,同时关闭Client读通道,此时Client进入TIME_WAIT状态。
- Server接收到Client响应的确认ACK后,关闭Server写通道,立即断开TCP连接,即转化为CLOSED状态。最后Client在TIME_WAIT状态下要等待2个MSL(Max Segment Lifetime),在Windows下默认为4分钟,即240秒,然后才进入CLOSED状态,此时TCP协议关闭连接过程彻底结束。
为何会有TIME_WAIT状态?
- 保证TCP全双工连接能够可靠关闭:因为由于网络IP的不可靠,client最后发送给server的确认ACK可能丢失,当服务端等待超时,会重新发送FIN报文段,若client已经关闭了,就收不到重发的FIN报文,最终server会收到RST(RESET)而不是ACK,认为连接错误而将问题报告给高层协议,虽然不会造成数据丢失,但是违背了TCP可靠性连接的特性,所以client要保持TIME_WAIT状态,保证再次收到FIN报文时,能使server收到ACK,最后正确关闭连接。
- 保证连接的重复报文段从网络中消失,避免新旧连接混淆:若client直接CLOSED,然后又再向server发起一个新连接,我们无法保证这个新连接与刚关闭连接的端口号是不同的。就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是会有特殊情况出现;假设新连接和已关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达server,由于新连接和老连接的端口号是一样的,又因为TCP判断不同连接的依据是socket pair,于是TCP就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。
服务器出现大量CLOSE_WAIT状态是什么原因,怎么解决?
- server端出现大量CLOSE_WAIT状态,可能是server端代码出现了问题,对方的socket连接已经关闭,而我方却由于某些原因,比如IO忙于读写,没有及时关闭连接,这个时候需要检查代码,尤其是释放资源的代码,或者处理请求的线程操作。
TCP的滑动窗口机制
滑动窗口左边的是已发送并且被确认的分组,滑动窗口右边是还没有轮到的分组。滑动窗口里面也分为两块,一块是已经发送但是未被确认的分组,另一块是窗口内等待发送的分组。随着已发送的分组不断被确认,窗口内等待发送的分组也会不断被发送。整个窗口就会往右移动,让还没轮到的分组进入窗口内。
滑动窗口起到的是一个限流的作用,即当前滑动窗口的大小决定了当前TCP的发包速率
(滑动窗口的大小取决于拥塞控制窗口和流量控制窗口两者的最小值)
- 流量控制原理:
TCP 全双工,客户端和服务器均可作为发送方或接收方,现假设一个发送方向接收方发送数据的场景。首先接收方有一块接收缓存,当数据到达时会先把数据放到缓存中,上层应用等缓存中有数据时就会到缓存中取数据。假如发送方没有限制地不断地向接收方发送数据,接收方的应用程序又没有及时把接收缓存中的数据读走,就会出现缓存溢出,数据丢失的现象,为了解决这个问题,引入流量控制窗口。假设应用程序最后读走的数据序号是 lastByteRead,接收缓存中接收的最后一个数据序号是 lastByteRcv,接收缓存的大小为 RcvSize,那么必须要满足 lastByteRcv - lastByteRead <= RcvSize 才能保证接收缓存不会溢出,所以定义流量窗口为接收缓存剩余的空间,也就是 Rcv = RcvSize - (lastByteRcv - lastByteRead)。只要接收方在响应 ACK 的时候把这个窗口的值带给发送方,发送方就能知道接收方的接收缓存还有多大的空间,进而设置滑动窗口的大小。 - 拥塞控制原理:
发送方先设置一个小的窗口值作为发送速率,当成功发包并接收到 ACK 时,便以指数速率增大发送窗口的大小,直到遇到丢包(超时/三个冗余 ACK ),才停止并调整窗口的大小。这么做能最大限度地利用带宽,又不至于让网络环境变得太过拥挤。
HTTP 与 HTTPS 的区别
HTTP协议以明文方式传输数据,不提供任何形式的数据加密,安全性低,为了解决HTTP的安全性问题,于是有了HTTPS协议,HTTPS在HTTP的基础上加入SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信提供加密。没有银弹,由于HTTPS需要保证安全性,它的性能自然比HTTP差一些。
HTTPS加密原理
client与server希望进行安全的通信,那么很自然的想到让传输的信息只有收发双方能够看懂,方法就是加密,首先想到的就是对称加密(主要基于大质数难以快速分解的原理),简单来说就是client和server各自持有一个相同的密钥,传递信息的时候用该密钥加密数据,在消息到达方再用该密钥解密,以此完成安全通信。对称加密中又涉及到加密算法的选择,通常的对称加密算法有:DES 、 3DES 、 AES ,通常实际中一般是多个客户端连接一个服务器,所以必然的需要各个客户端和服务器之间采用不同的加密方式。
怎样让每个client与server之间采用不同加密方式?
如何对不同的客户端机器采用不同的加密方式,很自然的想到这个密钥可以使用随机数,即客户端和服务器之间每次都基于一个随机数来产生加密算法(具体实现时经常会用到多个随机数),这个双方直接产生加密算法(即生成密钥)的过程就被称为协商。随之的关键问题就来了,双方之间的协商过程是透明的,也就是说任何中间人都可以截获协商的过程,这样就能获取我们的加密方式,那么为了解决这个问题,就需要对协商过程进行加密。
如何对协商过程进行加密?
之所以会产生密钥协商的过程,原因在于我们一开始选择了对称加密,双方需要持有相同的密钥,因此我们现在不能再使用对称加密了,不然就陷入死循环了。这个时候可以采用另一种加密方式对协商过程加密,即非对称加密,常见的非对称加密算法有:RSA 、 DSA,非对称加密算法的逻辑如下:
- 通信双方一方持有私钥,另一方持有公钥,通过私钥加密的信息都能通过公钥解密,但是通过公钥加密的信息只有私钥能够解密。
那么按照非对称加密的逻辑,我们让服务器持有私钥,客户端持有公钥,这样就能保证客户端给服务器发送消息的过程是安全的(反之服务器向客户端发送消息不安全),这样我们就可以把协商时的重要过程(即客户端把产生的对称密钥用公钥加密后再发送给服务器)安排到客户端给服务器发消息的过程中,这样就能保证协商时的安全性。
虽然非对称加密解决了密钥协商的安全性,但是这个时候问题又来了,非对称加密的前提是客户端需要获取公钥,client与server通信前并不知道对方身份,客户端怎么才能获取正确的公钥呢?
客户端怎么获得公钥?
正常逻辑只有两种办法:
- 客户端向服务端要
- 客户端向一个远程公共服务器要
方法2明显不行,先不说多了一次访问其他节点,怎么找到公共服务器也是个问题,所以还是用方法1,但是方法1也存在一个问题,这个时候客户端和服务端之间的获取公钥的通信过程被其他人篡改了怎么办,例如中间人把发送给客户端的公钥调包成他自己的,就是说获取公钥的客户端并不知道获得的公钥是不是真正服务器发送的。
客户端无法识别服务器和中间人的问题就是“身份验证”(所谓的CA)问题,也就是说我们需要为服务器向客户端发送公钥的过程加密。
这下玩完了,之前对称加密遇到瓶颈我们用非对称加密,现在非对称加密也遇到这种问题,明显这个时候这两种加密方式都不能再用了,不然就死循环了,这时候该怎么办,于是就有了第三方验证机构的产生。
引入第三方验证机构解决
有第三方权威机构产生公钥,首先我们自己保存第三方机构的公钥,然后第三方机构会使用私钥对服务器要发送给客户端的公钥进行加密,客户端收到这个加密后的公钥(也就是所谓的数字证书),就能通过自己保存的第三方机构公钥进行解密了。说到这里是不是觉得又绕回去了,我怎么知道我收到数字证书有没有被调包呢,现实中第三方机构不仅给我们正常公司发证书,也会给中间人搞事情的发,证书被调包后我们仍可以用CA的公钥来对证书解密(非对称加密逻辑);哈哈哈,不要着急,客户端如何验证证书的真伪呢?答案就是证书本身会告诉客户端如何验证真伪。比如,可以给每个证书设置一个唯一的证书编号,以及一个如何计算证书编号的方法,客户端收到证书后根据这个方法计算出自己想要获得的证书的编号,然后和证书上携带的编号比较来判断是否真伪,这里的证书编号就是数字签名。
以上就是HTTPS达到安全通信要求的一套流程逻辑,到此为止我们解释了HTTPS中的常用概念:对称加密,非对称加密,CA,数字证书,数字签名,以及为何会产生这些的原因。
简单总结一下:HTTPS为了保证客户端与服务端之间的安全通信,使用了对称加密算法来加密传输的信息,又为了保证协商对称加密算法的过程的安全使用了非对称加密,在非对称加密算法中,客户端需要获取公钥,而获取公钥的过程的安全性则又需要通过第三方机构(CA)颁发的数字证书来保证。总之就是通过这一系列机制协商出一个对称加密算法后,双方就可以通过该加密算法进行安全通信了。
至于框架层面是如何基于此封装出的一整套https接口那就是实现细节层面的事了,而实现原理则都是基于HTTPS协议底层这一套思想的,思路比结论重要。
简要谈一下TCP和UDP的异同点
- TCP面向连接,建立连接三次握手,断开连接四次挥手;UDP面向无连接,收发双方随时可以通信,只要接收方创建了Socket,设置监听端口,就能接收到达的UDP包,且能随时建立Socket连接发包。
- TCP能够控制发包的速率,具有流量控制和拥塞控制机制,主要通过控制滑动窗口的大小来控制数据的发送速率;UDP理论上可以无限向网络中发包,其发送速率取决于上层应用程序的设置。
- TCP能够保证可靠的数据传输,通过发包速率控制,重传控制,数据校验保证来提供可靠性数据传输;UDP只是基于IP的尽力而为服务传输数据,无法保证可靠性。
- TCP报文段头部占20个字节,消耗资源更多,且由于建立连接有握手机制,所以单位传输效率较低一些;UDP报文段头部占8个字节,单位传输效率更高。
在地址栏键入URL后,发生了什么过程
可以考虑从开机联网开始说起,更详细。
前奏阶段:获取本机IP地址,DNS服务器IP,网关路由器IP和MAC地址
首先主机需要准备一个DHCP报文,封装在一个UDP报文中,里面包括本机端口号68和目的端口号67,然后到网络层封装成IP数据包,里面包括本机初始IP0.0.0.0和广播地址255.255.255.255,接着到数据链路层封装成链路层帧,里面包括广播地址和本机网卡MAC地址,最后广播发送到本地局域网中。
这个数据包最终会被局域网中的DHCP服务器发现(可能有多个DHCP服务器),DHCP服务器把可用的IP地址列表返回给主机,然后操作系统会选择其中一个IP地址并发送给DHCP服务器,最后DHCP服务器会返回一个包含本机IP,DNS服务器IP,网关路由器IP的报文给主机。
之后主机就需要通过网关路由器的IP地址去获取网关路由器的MAC地址,这样我们才能把获取目标网站IP的DNS请求报文通过网关路由器发送给DNS服务器,这时我们就需要准备一个ARP请求报文,来请求获取网关路由器的MAC地址,该报文同样以广播的方式发送到局域网中,网关路由器接收到该ARP请求报文后就会把自己的MAC地址返回给主机
键入URL之后
第一步:获取域名的IP
首先要访问DNS服务器来获得目标网站的IP地址,所以我们首先需要把DNS请求报文封装到UDP报文中,然后封装到网络层的数据包中,填上源IP、目的DNS服务器IP,接着封装到链路层帧,填上网卡MAC地址和网关路由器MAC地址,之后这个DNS请求报文就会被网关路由器发送到DNS服务器。
假设DNS服务器已缓存该网站IP(如果没有,则会进一步层层向更高级的DNS服务器获取目标IP,直至根DNS服务器),DNS服务器会返回该域名的IP地址。
第二步:建立TCP连接
获取目标网站的IP后就可以与该网站的服务器建立TCP连接了。
建立TCP连接三次握手,参见上述详细过程。
第三步:进行数据交互
TCP连接建立之后,主机就可以向服务器发送HTTP请求了,通常是通过浏览器发送HTTP请求,服务器接收后会响应数据,web端接收数据后浏览器将数据页面渲染显示(省略了浏览器前端的渲染页面过程,前端问题需要把详细过程说出)。
HTTP常见状态码及含义
状态码的开头表示不同的含义:
- 1xx:指示信息,表示请求已接收,继续处理
- 2xx:成功,表示请求已被成功接收、理解、接受
- 3xx:重定向,表示完成请求必须进行进一步的操作
- 4xx:客户端错误,请求有语法错误或请求无法实现
- 5xx:服务端错误,服务器未能实现合法的请求
常见状态码:
- 200 OK:请求成功,正常返回响应信息
- 301 Moved Permanently:被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一
- 302 Found:客户端执行临时重定向,重定向临时,客户端应继续向原地址发送请求
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized:用户没有必要的凭据,表示当前请求需要用户验证
- 403 Forbidden:服务器收到请求,但是拒绝提供服务
- 404 Not Found:请求的资源不存在,输入了错误的URL
- 500 Internal Server Error:服务器发生不可预期的错误
- 503 Server Unavailable:服务器当前不能处理客户端请求,一段时间后可能恢复正常
Get请求和Post请求区别
- HTTP报文层面:get请求把信息放在URL,post请求把信息放在请求体body。(协议本身并没有规定get请求和post请求的长度限制)由于浏览器对URL都有长度限制(chrome最大8182字节),故get请求携带数据量有限。post请求则对数据大小没有限制。从形式上看,get请求把数据放在URL明显不太安全,post请求把数据放在请求体看似安全一些,其实两者在安全性上都不行,只是get请求更明显,想要保证安全的信息传输还是要使用HTTPS。
- 数据库层面:get请求符合幂等性要求和安全性,post请求则不符合。和http对两者作用的语义有关,get请求用于查看信息,不会改变服务器的信息,post请求用于改变服务器上信息。故get请求对数据库的一次或多次操作获得结果总是一致,符合幂等性要求。安全性则是指对数据库的操作不会改变数据库中的数据。
- 其他层面:get请求能够被缓存,能够保存在浏览记录里,能够保存为浏览器书签,post请求都不具备。缓存是get请求被广泛应用的根本,能够被缓存也是因为其幂等性和安全性,除了返回结果没有多余动作,所以绝大部分get请求都被cdn缓存了,大大降低了web服务器的负荷。
什么是Cookie和Session,Cookie一般如何使用,有哪些实现Session的机制,两者的区别
HTTP协议无状态,用户通过浏览器访问web应用时,如果没有保存用户状态的机制,那就不能持续跟踪用户的操作。比如典型的购物车,用户往购物车加了商品,返回继续浏览别的页面,你必须同时保证购物车的状态,好让用户继续往购物车加减东西,所以就有cookie这种东西。
Cookie可以说是浏览器的一种缓存机制,能够用来保存客户端与服务端之间的会话,cookie会将会话保存在客户端本地。以常见登录过程为例:
- 用户第一次在客户端浏览器向服务器发起登录请求
- 登录成功后,服务器就会把已登录用户的信息保存在cookie中,返回给浏览器
- 客户端浏览器接收cookie请求后,会把cookie保存在本地(可能是浏览器内存,也可能持久化到硬盘,视情况而定)
- 之后再次访问该服务器时,浏览器就会把本地的cookie带上,然后服务器就能根据cookie来获取用户信息
Session也是一种维持客户端和服务端会话的机制,和cookie不同,session会将会话信息保存在web服务器端。同样以登录为例:
- 用户第一次在客户端浏览器发起登录请求
- 登录成功后,服务端会将用户信息保存在服务器上,并返回该会话的一个唯一session标识(JSessionId)给浏览器
- 客户端浏览器会将这个唯一session标识保存起来
- 之后再次访问web服务器,浏览器就会把这个唯一session标识带上,然后服务器就能根据这个唯一标识找到该用户信息
看似过程相似,实则区别就在session只是一种会话机制,在大多数web应用中,session机制就是通过cookie来实现的,即session只是使用了cookie的功能,通过cookie的功能把会话信息保存在服务器端,并不使用cookie来保存会话(把JSessionId保存在cookie中)。
Session作为一种会话机制,也可以有不同的实现方式。以小程序为例,session实现方案如下:
- 用户登录服务器后,把用户登录信息保存在服务器端,可以采用redis(或其他)。比如给用户生成一个userToken,然后以userId为键,userToken为值保存到redis,然后在返回信息时把userToken带回给小程序端
- 小程序端接收到userToken,把它缓存起来,之后每次访问后端服务时都把userToken(base64加密)带上
- 在之后的服务交互中,服务端只要获取小程序端每次带来的userToken(base64解密),然后根据userId去redis里拿对应的userToken,和每次带来的userToken对比,就能确定用户的登录状态了
如何考虑分布式 Session 问题?
互联网公司为了支撑更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在A服务器登录了,第二次请求跑到服务B就会出现登录失效问题。
分布式 Session 一般会有以下几种解决方案:
- Nginx ip_hash 策略:服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。
- Session 复制:任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。
- 共享 Session(通常采用这种):服务端无状态化,将用户的 Session 等信息使用缓存中间件来统一管理,保障分发到每一个服务器的响应结果都一致。
如何解决跨域请求?Jsonp 跨域的原理是什么?
针对跨域请求,必须了解浏览器的同源策略,同源策略/SOP(Same origin policy)是一种约定,由 Netscape 公司 1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS、CSFR 等攻击。所谓同源是指”协议+域名+端口”三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源。
解决跨域请求的常用方法是:
- 通过代理来避免,如使用 Nginx 在后端转发请求,避免了前端出现跨域问题。
- 通过 Jsonp 跨域
- 其它跨域解决方案
Jsonp 跨域原理:浏览器的同源策略把跨域请求都禁止了,但是页面中的 <script><img><iframe>
标签是例外,不受同源策略限制。Jsonp 就是利用 <script>
标签跨域特性进行跨域数据访问。
JSONP 的理念是,与服务端约定好一个回调函数名,服务端接收到请求后,将返回一段 Javascript,在这段 Javascript 代码中调用了约定好的回调函数,并且将数据作为参数进行传递。当网页接收到这段 Javascript 代码后,就会执行这个回调函数,这时数据已经成功传输到客户端了。
JSONP 缺点:它只支持 GET 请求,不支持 POST 等其他 HTTP 请求。
参考资料:《计算机网络:自顶向下方法》
还没有评论,来说两句吧...