赞
踩
**《350页前端校招面试题精编解析大全》**内容大纲主要包括 HTML,CSS,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,项目,职业发展等等
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
大致的过程是客户端发一个syn之后,服务端将这个连接放入到backlog队列,在收到客户端的ack之后将这个请求移到accept队列。所以accept一定是发生在三次握手之后,connect只是发一个syn而已
Accept根本不参与三次握手,服务器只要Listen,客户端connect是与服务器内核握手,connect完成之后,服务器都不需要写Accept,客户端就已经可以发送数据了,你完全可以让这批数据在服务器里躺一年之后,再Accept也可以
tcp三次握手的过程,accept发生在三次握手哪个阶段?
第一次握手:客户端发送syn包(syn=j)到服务器。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个ASK包(ask=k)。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)。
三次握手完成后,客户端和服务器就建立了tcp连接。这时可以调用accept函数获得此连接
TCP通信双方都可以释放连接
TCP的连接的拆除需要发送四个包,因此称为四次挥手。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。
TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
以第一次挥手为例各个标志位的含义:
FIN:表明这是一个TCP连接释放报文段
ACK:对之前接收的报文段进行确认
ack:服务端传送过来的字节的最后一个字节序号+1
seq:客户端发送字节的最后一个字节序号+1
客户端时间等待状态是否有必要?
如果客户端最后一次挥手发送过程中丢失,会导致服务器一直重传TCP连接释放,无法进入关闭状态
添加等待状态可以确保服务器收到最后一个TCP确认报文段而进入关闭状态,另外,客户端在发完最后一个TCP确认报文段后再经过2MLS,可以使本次连接持续时间内所产生的所有报文段都从网络中消失,使下一个TCP连接中不会出现旧连接中的报文段。
如果客户端出现故障,客户端如何发现?
TCP服务器每次收到一次TCP客户端进程的数据,就重新设置并启动保活计时器(2h),若保活周期内未收到TCP客户端的数据,TCP服务器就像TCP客户端发送探测报文段,以后每75s发送一次,若一脸发送10个仍没收到TCP客户端的响应,TCP服务端就认为TCP客户端出现了故障,接着就关闭这个链接。
当客户端最后一次发送消息时并没有直接进入close状态而是进入TIME\_WAIT状态,这是因为TCP是面向连接的协议,每一次发送都需要确认对方是否收到消息。客户端最后一次发送消息时可能会由于网络等其他原因导致服务器收不到消息,服务器就会选择从新给客户端发送一个FIN的包,如果客户端处于关闭状态将永远也收不到服务器发给它的消息了。至于这个时间要等多久才能确认对方收到了消息呢。
报文在网络中有一个最大生存时间MSL超过这个时间就会被丢弃并通知源主机。
TIME\_WAIT 要等待 2MSL 才会进入 CLOSED 状态。
ACK包到达服务器需要MSL时间,服务器重传 FIN 包也需要MSL时间,2MSL 是数据包往返的最大时间,通常为2min,如果2MSL后还未收到服务器重传的FIN 包,就说明服务器已经收到了ACK包,此时由TIME\_WAIT状态转变为CLOSED状态.
TCP的keepalive的来源
双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会,那么在长时间无数据交互的时间段内,交互双方都有可能出现掉电、死机、异常重启等各种意外,当这些意外发生之后,这些TCP连接并未来得及正常释放,那么,连接的另一方并不知道对端的情况,它会一直维护这个连接,长时间的积累会导致非常多的半打开连接,造成端系统资源的消耗和浪费,为了解决这个问题,在传输层可以利用TCP的保活报文来实现。
TCP的keepalive的作用
利用保活探测功能,可以探知这种对端的意外情况,从而保证在意外发生时,可以释放半打开的TCP连接。
三次握手状态:
(1) 第一次握手[同步已发送状态,SYN-SENT]
(2) 第二次握手[同步收到状态,SYN-REVD]
(3) 第三次握手[已建立连接状态,ESTABLISHED]
四次挥手状态:
(1) FIN-WAIT-1(终止等待1)状态[客户端]
(2) CLOSE-WAIT(关闭等待)状态[服务端]
(3) FIN-WAIT-2(终止等待2)状态[客户端]
(4) LAST-ACK(最后确认)状态[服务端]
(5) TIME-WAIT(时间等待)状态[客户端] 这个是考点!!!
(6) CLOSED状态[服务端]
TCP连接为什么是三次的问题?
TCP协议为了实现可靠传输,通信双方需要判断自己已经发送的数据包是否都被接收方收到, 如果没收到, 就需要重发。 为了实现这个需求,很自然地就会引出序号(sequence number) 和 确认号(acknowledgement number) 的使用。
故为了可靠传输,发送方和接收方始终需要同步SYN序号,不仅客户端向服务器端发送SYN包请求连接,并且服务器端发送ACK包(确认包)同意请求,也需要向客户端发送SYN包请求连接,并得到客户端的ACK包(确认包),只有双方都发送并接收响应,才算连接成功!
TCP断开连接为什么是四次的问题?
TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。
TCP是全双工模式,这就意味着,当客户端发出
FIN
报文段给服务器端时,只是表示客户端已经没有数据要发送了,即表示它的数据已经全部发送完毕了;但是,这个时候客户端还是可以接受来自服务器端的数据的;当服务器端返回ACK
报文段时,表示它已经知道了客户端没有数据发送了,但是服务器还是可以发送数据到客户端的;当服务器也发送了FIN
报文段时,这个时候就表示客户端也没有数据要发送了,就等于告诉我也没有数据要发送了,之后等到客户端返回ACK
报文段的时候,彼此才会真正的,愉快的中断这次TCP连接。
我们说在建立TCP连接的过程中,服务器发送SYN-ACK包之后,收到客户端的ACK包之前的状态叫做半连接状态,此时服务器处于SYN-RECV状态,当服务器收到ACK包后,称为ESTABLISHED状态
**SYN攻击指的是攻击客户端,在短时间内伪造出大量的不存在的IP地址,向服务器端进行发送SYN包,此时服务器回复确认包(ACK),并等待客户端的确认,由于很大的IP地址是不存在的,导致服务器需要不断地进行重复发送直至超时!**而这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者将引起网络堵塞甚至系统瘫痪.
解决方案:
在Linux系统下可以如下命令检测是否被Syn攻击
netstat -n -p TCP | grep SYN_RECV
一般较新的TCP/IP协议栈都对这一过程进行修正来防范Syn攻击,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等等,但是都不能完全地防范SYN攻击.
首先我们需要知道几个概念:
第一次握手:建立连接时,客户端发送SYN包(seq=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到SYN包,将SYN和ACK标识都置为1,然后设置(seq=y,ack=x+1),向客户端发送一个SYN+ACK包,此时服务器进入SYN_RECV状态.
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包,将ACK置为1,S此时无需SYN,(seq=x+1,ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
所以 :
这题中,第三次的seq = x + 1 = 2000,ack = y + 1 = 1000,说明第二次的seq = y = 1999,ack = x + 1 = 1000
TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。
(1) 发送方原因
TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事:
- 只有上一个分组得到确认,才会发送下一个分组
- 收集多个小分组,在一个确认到来时一起发送
Nagle算法造成了发送方可能会出现粘包问题
(2) 接收方原因
TCP接收到数据包时,并不会马上交到应用层进行处理,或者说应用层并不会立即处理。实际上,TCP将接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。
(1)发送方
对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。
(2)接收方
接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。
(2)应用层
应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。
解决办法:循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成,但是如何判断每条数据的长度呢?
TCP为了保证可靠传输并减少额外的开销(每次发包都要验证),采用了基于流的传输,基于流的传输不认为消息是一条一条的,是无保护消息边界的(保护消息边界:指传输协议把数据当做一条独立的消息在网上传输,接收端一次只能接受一条独立的消息)。
UDP则是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。
举个例子:有三个数据包,大小分别为2k、4k、6k,如果采用UDP发送的话,不管接受方的接收缓存有多大,我们必须要进行至少三次以上的发送才能把数据包发送完,但是使用TCP协议发送的话,我们只需要接受方的接收缓存有12k的大小,就可以一次把这3个数据包全部发送完毕。
XSS攻击的核心原理是:不需要你做任何的登录认证,它会通过合法的操作(比如在url中输入、在评论框中输入),向你的页面注入脚本(可能是js、hmtl代码块等)
最后导致的结果可能是:盗用Cookie破坏页面的正常结构,插入广告等恶意内容D-doss攻击
(1)服务器发送给客户端一个token;
(2)客户端提交的表单中带着这个token。
(3)如果这个 token 不合法,那么服务器拒绝这个请求。
简单的理解,SQL注入就是我们将SQL命令插入到WEB表单或者是页面请求url的请求字符串,最终达到欺骗服务器的执行恶意的SQL命令的目的。
总结来说,SQL注入就是指通过构建特殊的输入作为参数传入WEB应用程序,而这些输入大多数情况下都是SQL语法中的一些组合,通过执行SQL语句进而执行了攻击者携带的操作。
导致SQL注入的主要原因是没有细致地过滤用户输入的数据,致使非法数据侵入系统
案例 : 我们在用户登录的时候,需要输入用户名和密码进行登录,此时如果我们没有防范SQL注入,在用户登录信息中输入以下信息,将会免密登录,这导致对我们的系统造成了极大的不安全性!
用户名 :or 1 = 1 –
密码 :
首先我们来说一下后台验证用户名和密码的SQL语句为 :
select \* form user_table where username = 'username' and password = 'password';
此时我们输入上面的用户名和密码以后 :
select \* form user_table where username = '' or 1 = 1 -- and password = 'password';
这里就会出现问题了:
我们说在SQL语句中, – 表示注释,此时 1 = 1为true,前面用 ‘or‘进行连接,则该条件一定成立,故我们登陆成功
此时如果我们注入的语句不是登陆,而是删除数据表结构,那如果没有对SQ注入进行防范,这样的危害是及其大的!!!
1. 对于普通用户和系统管理员用户的权限进行严格的划分
如果是对数据库的一些删除,建立等操作,我们需要系统管理用户才能进行操作,即我们在设计数据库时,把系统管理员的用户与普通用户区分开来。
2.强迫使用参数化语句
如果在编写SQL语句的时候,用户输入的变量不是直接嵌入到SQL语句。而是通过参数来传递这个变量的话,那么就可以有效的防治SQL注入式攻击
3. 加强对用户输入的验证
加强对用户输入内容的检查与验证
4. 使用预编译(PreStatement)
PreparedStatement会对SQL进行了预编译,在第一次执行SQL前数据库会进行分析、编译和优化,同时执行计划同样会被缓存起来,它允许数据库做参数化查询。在使用参数化查询的情况下,数据库不会将参数的内容视为SQL执行的一部分,而是作为一个字段的属性值来处理,这样就算参数中包含破环性语句(or ‘1=1’),也只能作为参数,而不能作为SQL语句内容,故不会被执行。
大部分的SQL框架,例如: Hibernate,Mybatis,JPA等都支持预编译,故能够防范SQL注入问题
HTTP是超文本传输协议的缩写,它是用来传送WWW方式的数据,按层次划分,它属于应用层.HTTP协议采用了请求/响应模型.
TCP是指传输控制协议,是一种面向连接的,可靠的,基于字节流的传输层通信协议. 其中用户数据报协议(UDP)也是传输层另一种重要的传输协议(后面会进行比较) ,他属于传输层。
IP指的是网络之间互连的协议,也就是为计算机网络相互连接进行通信而设计的协议,它属于网络层.
如今的IP网络使用32位地址,以点分十进制表示,如192.168.0.1
地址格式为:IP地址 = 网络地址+主机地址 或 IP地址 = 网络地址 + 子网地址 + 主机地址
一个HTTP请求报文由四个部分组成 : 请求行、请求头部、空行和请求数据(请求体)
一个HTTP响应报文也由四个部分组成:状态行、响应头部,空行和响应体
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。
简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比HTTP协议安全
总结两者主要的区别如下所示:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
1. 长连接(Persistent Connection)
HTTP1.1支持长连接和请求的流水线处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启长连接keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。HTTP1.0需要使用keep-alive参数来告知服务器端要建立一个长连接。
2. 节约带宽
HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,客户端接收到100才开始把请求body发送到服务器;如果返回401,客户端就可以不用发送请求body了节约了带宽。
3. HOST域
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname),HTTP1.0没有host域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都支持host域,且请求消息中如果没有host域会报告一个错误(400 Bad Request)。
4. 缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
5. 错误通知的管理
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
虽然说非对称加密安全,但是由于和对称加密比较来说,速度较慢(指的是加密和解密的速度而言),故我们https采用了将对称加密和非对称加密结合的方式,即我们将对称加密的秘钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用非对称的私钥进行解密得到对称加密的秘钥,此时双方就可以使用对称加密的秘钥进行通信沟通了,这样既保证了安全性,又增加了通信的速度,即加密和解密的速度.
对称加密:快速简单,加密和解密都使用同样的秘钥。
非对称加密:安全,使用一对密钥,公钥/私钥。私钥由一方安全保管,公钥可以发给任何请求他的人,发送请求时通过公钥对消息进行加密,只有拥有私钥的人才能对你的消息进行解密,安全性大大提高。
SSL加密过程:
1.客户端向服务端发送请求
2.服务端返回给客户端公钥
3.客户端使用公钥对信息加密后在想服务端发送请求
4.服务端通过私钥对信息解密
RSA加密算法:
一种公钥密码体制,公钥公开,私钥保密,它的加密解密算法是公开的。 RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密。
为了防止证书颁发过程中被人修改,出现了数字签名。
CA机构将证书内容用hash算法生成hash字符串1,并用CA私钥加密发送给服务端
服务端用CA公钥解密得到hash字符串1,同时也将证书内容用hash算法生成hash字符串2,如果hash字符串1与hash字符串2相同,说明证书没被修改过
1.多路复用
HTTP2.0使用了多路复用的技术,做到**同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。**HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。
2. 头部数据压缩
HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
3. 服务器推送
服务端推送是一种在客户端请求之前发送数据的机制。网页使用了许多资源:HTML、样式表、脚本、图片等等。在HTTP1.1中这些资源每一个都必须明确地请求。这是一个很慢的过程。浏览器从获取HTML开始,然后在它解析和评估页面的时候,增量地获取更多的资源。因为服务器必须等待浏览器做每一个请求,网络经常是空闲的和未充分使用的.
为了改善延迟,HTTP2.0引入了server push,它允许服务端推送资源给浏览器,在浏览器明确地请求之前,免得客户端再次创建连接发送请求到服务器端获取。这样客户端可以直接从本地加载这些资源,不用再通过网络。
下面这张图是由TMX总结 :
超文本传输协议,基于TCP/IP通信协议来传递数据
HTTP/0.9是第一个版本的HTTP协议,已过时。它的组成极其简单,只允许客户端发送GET这一种请求,且不支持请求头。由于没有协议头,造成了HTTP/0.9协议只支持一种内容,即纯文本。
HTTP/0.9具有典型的无状态性,每个事务独立进行处理,事务结束时就释放这个连接。由此可见,HTTP协议的无状态特点在其第一个版本0.9中已经成型。一次HTTP/0.9的传输首先要建立一个由客户端到Web服务器的TCP连接,由客户端发起一个请求,然后由Web服务器返回页面内容,然后连接会关闭。如果请求的页面不存在,也不会返回任何错误码。
相对于HTTP/0.9增加了如下主要特性:
是目前使用最广泛的协议版本。相对于HTTP/1.0新增了以下内容:
HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
提供了范围请求功能,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。这是支持文件断点续传的基础。
提供了虚拟主机的功能,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
HTTP/1.1在1.0的基础上加入了一些cache的新特性,引入了实体标签,一般被称为e-tags,新增更为强大的Cache-Control头。
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
相对于HTTP/1.1新增了以下内容:
HTTP 2.0 的所有帧都采用二进制编码
- 帧:客户端与服务器通过交换帧来通信,帧是基于这个新协议通信的最小单位。
- 消息:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。
- 流:流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符(1、2 … N);
多路复用允许同时通过单一的HTTP/2.0 连接发起多重的请求-响应消息。有了新的分帧机制后,HTTP/2.0不再依赖多个TCP 连接去处理更多并发的请求。每个数据流都拆分成很多互不依赖的帧,而这些帧可以交错(乱序发送),还可以分优先级。最后再在另一端根据每个帧首部的流标识符把它们重新组合起来。HTTP 2.0 连接都是持久化的,而且客户端与服务器之间也只需要一个连接(每个域名一个连接)即可。
HTTP/1.1 的首部带有大量信息,而且每次都要重复发送。HTTP/2.0 要求通讯双方各自缓存一份首部字段表,从而避免了重复传输。
浏览器可以在发现资源时立即分派请求,指定每个流的优先级,**让服务器决定最优的响应次序。**这样请求就不必排队了,既节省了时间,也最大限度地利用了每个连接。
把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。
快速UDP互联网连接
2个主要特征:
基于TCP的HTTP/2,尽管从逻辑上来说,不同的流之间相互独立,不会相互影响,但在实际传输方面,数据还是要一帧一帧的发送和接收**,一旦某一个流的数据有丢包,则同样会阻塞在它之后传输的流数据传输**。而基于UDP的QUIC协议则可以更为彻底地解决这样的问题,让不同的流之间真正的实现相互独立传输,互不干扰。
当前移动端的应用环境,用户的网络可能会经常切换,比如从办公室或家里出门,WiFi断开,网络切换为3G或4G。基于TCP的协议,由于切换网络之后,IP会改变,因而之前的连接不可能继续保持。而基于UDP的QUIC协议,则可以内建与TCP中不同的连接标识方法,从而在网络完成切换之后,恢复之前与服务器的连接。
GET和POST本质上没有区别
HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。不同的浏览器(发起http请求)和服务器(接受http请求)就是不同的运输公司,他们对get/post请求的数据处理不同。
GET和POST还有一个重大区别
GET产生一个TCP数据包;POST产生两个TCP数据包。
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
状态码 | 类别 | 原因短语 |
---|---|---|
1XX | Informational(信息性状态码,服务器给客户端的信息) | 接收的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法进行处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
状态码 | 描述 |
---|---|
200 OK | 请求已正常处理 |
301 Moved Permanently | 永久性重定向 : 请求的资源已经被分配了新的URI,以后应使用资源现在所指的URI |
302 Found | 临时性重定向 : 和301相似,但302代表的资源不是永久性移动,只是临时性性质的。换句话说,已移动的资源对应的URI将来还有可能发生改变 |
303 See Other | 303状态码和302状态码有着相同的功能,但303状态码明确表示客户端应当采用GET方法获取资源,这点与302状态码有区别 |
304 Not Modified | 该状态码表示客户端发送附带条件的请求时(采用GET方法的请求报文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部)服务端允许请求访问资源,但因发生请求未满足条件的情况后,直接返回304.。 |
400 Bad Request | 服务器端无法理解客户端发送的请求,请求报文中可能存在语法错误((前端提交到后台的数据应该是json字符串类型,但是前端没有将对象JSON.stringify转化成字符串)) |
401 Unauthorized | 该状态码表示发送的请求需要有通过HTTP认证(BASIC认证,DIGEST认证)的认证信息 |
403 Forbidden | 不允许访问那个资源。该状态码表明对请求资源的访问被服务器拒绝了。(权限,未授权IP等) |
404 Not Found | 服务器上没有请求的资源。路径错误等 |
500 Internal Server Error | 该状态码表明服务器端在执行请求时发生了错误。也有可能是web应用存在bug或某些临时故障 |
503 Service Unavailable | 服务器暂时处于超负载或正在停机维护,现在无法处理请求 |
502 | 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。 |
504 | 作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应。 |
如果在cookie中设置了HttpOnly,那么通过程序(js脚本)将无法读取到cookie信息,这样能有效防止XSS攻击
表示来源,正确英语拼法是Referrer,为了向后兼容,将错就错
在www.google.com里有一个
www.baidu.com
链接,那么点击这个www.baidu.com
,它的header信息里就有:Referer=http://www.google.com,可以利用这个来防止盗链了,比如我只允许我自己的网站访问我自己的图片服务器,那我的域名是www.google.com
,那么图片服务器每次取到Referer来判断一下是不是我自己的域名www.google.com
,如果是就继续访问,不是就拦截。直接在地址栏中输入URL的地址是不会包含referer字段的,因为他不是藏一个地方链接过去的
允许 Referer 为空,意味着你允许比如浏览器直接访问,就是空
是一个计算机通信协议,该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程.它是建立在Socket之上
RPC实现远程调用的策略:
(1) 采用何种网络通讯协议?
比较流行的RPC框架,采用的都是TCP作为底层传输协议
(2)数据传输的格式是怎么样的?
不同于HTTP,RPC远程过程调用需要让调用者和被调用者采用相同的数据传输格式,就好比两个人使用同一种语言进行交流沟通一样.
下面是RPC的调用流程图:
HTTP称为超文本传输协议,是一种应用层的协议,规定了网络传输的请求格式、响应格式、资源定位和操作的方式等。但是底层采用什么网络传输协议,并没有规定,不过现在都是采用TCP协议作为底层传输协议.
客户端通过HTTP向服务器端发送请求,并接受响应的流程:
常用的RPC框架: webservie(cxf)、dubbo
HTTP客户端工具: HTTPClient
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个Socket。建立网络通信连接至少要一对端口号(Socket)。Socket本质是编程接口(API).
当然我们也可以理解为: Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
在高并发短连接的server端,当server处理完client的请求后立刻close socket此时会出现time_wait状态,然后如果client再并发2000个连接,此时部分连接就连接不上了,用linger强制关闭可以解决此问题,但是linger会导致数据丢失,linger值为0时是强制关闭,无论并发多少多能正常连接上,如果非0会发生部分连接不上的情况!(可调用setsockopt设置套接字的linger延时标志,同时将延时时间设置为0。)
TIME_WAIT是TCP连接断开时必定会出现的状态。是无法避免掉的,这是TCP协议实现的一部分。
在WINDOWS下,可以修改注册表让这个时间变短一些,time_wait的时间为2msl,默认为4min.你可以通过改变TcpTimedWaitDelay的量,把它缩短到30s.TCP要保证在所有可能的情况下使得所有的数据都能够被投递。当你关闭一个socket时,主动关闭一端的socket将进入TIME_WAIT状态,而被动关闭一方则转入CLOSED状态,这的确能够保证所有的数据都被传输。但是这样也会给我们带来两个问题 :
(1) 我们没有任何机制保证最后的一个ACK能够正常传输
(2) 网络上仍然有可能有残余的数据包(wandering duplicates),我们也必须能够正常处理
由于TIME_WAIT状态所带来的相关问题,我们可以通过设置SO_LINGER标志来避免socket进入TIME_WAIT状态,这可以通过发送RST而取代正常的TCP四次握手的终止方式。但这并不是一个很好的主意,TIME_WAIT对于我们来说往往是有利的,下面我们来谈谈TIME_WAIT的作用
1. 可靠地实现TCP全双工连接的终止;
如果服务器最后发送的ACK因为某种原因丢失了,那么客户一定会重新发送FIN,这样因为有TIME_WAIT的存在,服务器会重新发送ACK给客户,如果没有TIME_WAIT,那么无论客户有没有收到ACK,服务器都已经关掉连接了,此时客户重新发送FIN,服务器将不会发送ACK,而是RST,从而使客户端报错。也就是说,TIME_WAIT有助于可靠地实现TCP全双工连接的终止。
2. 允许老的重复分节在网络中消逝。
如果没有TIME_WAIT,我们可以在最后一个ACK还未到达客户的时候,就建立一个新的连接。那么此时,如果客户收到了这个ACK的话,就乱套了,必须保证这个ACK完全死掉之后,才能建立新的连接。也就是说,TIME_WAIT允许老的重复分节在网络中消逝。
ACK包到达服务器需要MSL时间,服务器重传 FIN 包也需要MSL时间,2MSL 是数据包往返的最大时间,通常为2min,如果2MSL后还未收到服务器重传的FIN 包,就说明服务器已经收到了ACK包,此时由TIME_WAIT状态转变为CLOSED状态.
如果 TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了。第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二个连接。TCP实现必须防止某个连接的重复报文在连接终止后出现,所以让TIME_WAIT状态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被丢弃。建立第二个连接的时候,不会混淆。
每个应用程序都是一个进程,每个进程都有自己独立的一块内存空间,一个进程可以有多个线程。
进程的三种状态:就绪态(以获得除cpu外的所有资源),阻塞态,执行态
进程中的一个执行任务(控制单元)。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可以共享数据。
1.1匿名管道(半双工,数据只能单向移动,面向字节流,允许具有血缘关系的进程通信)
两个文件描述符指向管道的两端
1.2有名管道(半双工,允许无亲缘关系的进程通信)
(发送进程添加消息到队列的末尾,接收进程在队列头部接收消息,消息一旦被接收就会从队列中删除,类似FIFO)
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。
信号量工作原理 :
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
在信号量进行PV操作时都为原子操作(因为它需要保护临界资源)
共享内存就是允许两个或多个进程共享一定的存储区。共享内存没有任何的同步与互斥机制,所以要使用信号量来实现对共享内存的存取的同步
可用于不同机器间的进程通信
如上图所示,在浏览器的地址栏中输入url : 此时执行过程简单地介绍如下所示
第一步 : 我们的DNS域名解析器会对url进行域名解析,找到对应的IP节点进行返回
第二步 : 拿到我们访问的IP,我们就要与对应的服务器建立TCP连接(三次握手)
第三步 : TCP连接建立成功,我们就可以向服务器发送HTTP请求了,当服务器获取我们的请求,进行处理,然后将请求的响应返回给我们
第四步 : 关闭TCP连接(四次挥手)
DNS是进行域名和与之相对应的IP地址转换的服务器
浏览器会首先搜索浏览器自身的DNS缓存,如果浏览器自身的缓存里面没有找到对应的条目,
那么浏览器会搜索操作系统自身的DNS缓存,操作系统域名解析的过程是读取hosts文件(位于C:\Windows\System32\drivers\etc),如果在hosts
文件中也没有找到对应的条目,
浏览器就会找TCP/IP参数中设置的首选DNS服务器(本地DNS服务器)发起一个DNS的系统调用(运营商dns-->
根(13台)域名服务器-->
顶级域名服务器-->
域名注册商服务器)
从客户端到本地DNS服务器是属于递归查询,而DNS服务器之间就是的交互查询就是迭代查询。
将URL对应的各种资源,通过浏览器渲染引擎,输出可视化的图像
渲染引擎主要包括:html解析器,css解析器,布局,js引擎
html引擎:将html文本解释成DOM树(文档对象模型)
css解释器:为dom中的各个元素对象加上样式信息(CSS对象模型)
布局:将dom和css样式信息结合起来,计算他们的大小及位置信息,构建(渲染树)
js引擎:解释js代码并把代码逻辑对应的dom和css改动信息应用到布局中去
输入一个网址以后,首先会进行DNS域名解析,找到目标的IP地址,然后和目标地址建立TCP连接,连接成功以后,发送HTTP请求,目标服务器处理完请求以后,返回响应结果,最后关闭TCP连接
主机A首先查看自己的ARP缓存,检查是否含有主机B的IP到MAC地址的映射,如果存在映射,则构造报文,目的IP为主机B的IP,源IP为主机A的IP,目的MAC为主机B的MAC,源MAC为主机A的MAC,将报文发送给交换机C.交换机C进行MAC地址表学习,将主机A和MAC和报文入端口号记录下来,然后交换机C查看自己的MAC转发表,检查是否含有主机B的MAC到端口的映射,如果有对应的端口,则获取对应的端口,将报文从此端口转发出去,报文到达主机B.如果交换机C没有主机B的MAC转发映射表,则采用洪泛的形式广播报文,主机B收到报文后向主机A进行回复,交换机C进行MAC表学习,将主机B的MAC和报文入端口号记录下来
如果主机A没有主机B的ARP映射,主机A需要发送ARP请求,以获取主机B的MAC,将报文发往交换机C,交换机C采用洪泛的形式广播报文,主机B收到广播报文后,在自己的ARP缓存表中写入主机A的IP到MAC的映射,将自己的MAC封装到ARP回复报文中,单播给主机A,主机A获取到主机B的MAC后,在自己的ARP缓存表中写入主机B的IP到MAC的映射,构造报文发送给主机B,过程同上。
主机B向主机A回复报文的过程类似。
主机A查看自己的ARP缓存表,检查是否有路由器E的IP到MAC的映射,如果有映射,获取路由器E的MAC,构造报文,目的IP为主机B的IP,源IP为主机A的IP,目的MAC为路由器E的MAC,源MAC为主机A的MAC,将报文通过交换机C发往路由器E,过程同上。 如果主机A没有路由器E的IP到MAC的映射,需要发送ARP请求,获取路由器E的MAC,过程同上。路由器E收到主机A的报文后,剥离报文的MAC帧头,查询路由表,发现目标主机B所在的网络是直连的,查看自己的ARP缓存表,如果有主机B的IP到MAC的映射关系,获取主机B的MAC,封装报文MAC帧头,目的MAC为主机B的MAC,源MAC为路由器E的MAC,将报文通过交换机D发往主机B,如果路由器E没有主机B的IP到MAC的映射关系,需要发送ARP请求,获取主机B的MAC,过程同上。
主机B向主机A回复报文的过程类似。
注意 :
ARP协议指的是地址解析协议(Address Resolution Protocol),是根据**IP地址获取物理地址(MAC地址)**的一个TCP/IP协议.
在计算机间通信的时候,计算机要知道目的计算机是谁(就像我们人交流一样,要知道对方是谁),这中间需要涉及到MAC地址,而MAC是真正的电脑的唯一标识符。
我们通过两个主机之间的ping连接,来看一下简单的ARP请求应答
PC1依据OSI模型 :
① 依次从上至下对数据进行封装,包括对ICMP Date加IP包头的封装,但是到了封装MAC地址的时候
② PC1首先查询自己的ARP缓存表,发现没有IP2和他的MAC地址的映射,这个时候MAC数据帧封装失败。我们使用ping命令的时候,是指定PC2的IP2的,计算机是知道目的主机的IP地址,能够完成网络层的数据封装,因为设备通信还需要对方的MAC地址,但是PC1的缓存表里没有,所以在MAC封装的时候填入不了目的MAC地址。
那么PC1为了获取PC2的MAC地址 :
③ PC1要发送询问信息,询问PC2的MAC地址,询问信息包括PC1的IP和MAC地址、PC2的IP地址,这里我们想到一个问题,即使是询问信息,也是需要进行MAC数据帧的封装,那这个询问信息的目的MAC地址填什么呢,规定当目的MAC地址为ff-ff-ff-ff-ff-ff时,就代表这是一个询问信息,也即使后面我要说的广播。
PC2收到这个询问信息后,将这里面的IP1和MAC1(PC1的IP和MAC)添加到本地的ARP缓存表中,然后 :
④ PC2发送应答信息,对数据进行IP和MAC的封装,发送给PC1,因为缓存表里已经有PC1的IP和MAC的映射了呢。这个应答信息包含PC2的IP2和MAC2。PC1收到这个应答信息,理所应当的就获取了PC2的MAC地址,并添加到自己的缓存表中。
经过这样交互式的一问一答,PC1和PC2都获得了对方的MAC地址,值得注意的是,目的主机先完成ARP缓存,然后才是源主机完成ARP缓存。之后PC1和PC2就可以真正交流了。
对于交换机而言,它也具有记忆功能,会基于源MAC地址建立一个CAM缓存表(记录MAC对应接口的信息),理解为当PC1发送消息至交换机的Port1时,交换机会把源MAC(也就是MAC1)记录下来,添加一条MAC1和Port1的映射,之后交换机可以根据MAC帧的目的MAC进行端口转发
它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
(1)外形上:
交换机通常端口比较多看起来比较笨重,而路由器的端口就少得多体积也小得多
(2)工作层次不同:
最初的交换机工作在数据链路层,而路由器则工作网络层
(3)数据的转发对象不同:
交换机是根据MAC地址转发数据帧,而路由器则是根据IP地址来转发IP数据。
(4)”分工“不同
交换机主要是用于组建局域网,而路由器则是负责让主机连接外网。
(5)冲突域和广播域
交换机分割冲突域,但是不分割广播域,而路由器分割广播域。
(6)工作原理
交换机的原理比较简单,一般都是采用硬件电路实现数据帧的转发
路由器工作在网络层,肩负着网络互联的重任,要实现更加复杂的协议,具有更加智能的转发决策功能,一般都会在在路由器中跑操作系统,实现复杂的路由算法,更偏向于软件实现其功能。
(7)安全性能
路由器一般有防火墙的功能,能够对一些网络数据包选择性过滤。现在的一些路由器都具备交换机的功能,一些交换机具备路由器的功能,被称为3层交换机,广泛使用。相比较而言,路由器的功能较交换机要强大,但是速度也较慢,价格昂贵,三层交换机既有交换机的线性转发报文的能力,又有路由器的良好的路由功能因此得到广泛的使用
由于我们使用本地域名解析器进行解析,获取源服务器IP导致每一次获取数据,都要去源服务器进行访问获取,造成性能的损失的降低,故我们在网络各处部署节点服务器,构建CDN系统,当我们使用本地DNS域名系统进行解析的时候,DNS系统会将域名解析交给CNAME指向的专用的DNS服务器,通过CDN的DNS服务器获取到一台合适的缓存服务器IP给我们,这里的合适性指的是(服务器距离我们的距离位置,该服务器上是否存在我们需要的内容等等…),此时我们就与该缓存服务器建立TCP连接,已经后续的HTTP请求获取数据,得到响应等过程,如果该节点服务器不能满足我们的需求,我们会层层向它的上级服务器进行访问,直到源服务器为止.
(Content Delivery Network)
就近访问原理:采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。cdn就是用来加速的,他能让用户就近访问数据,这样就更更快的获取到需要的数据。
举个例子,现在服务器在北京,深圳的用户想要获取服务器上的数据就需要跨越一个很远的距离,这显然就比北京的用户访问北京的服务器速度要慢。但是现在我们在深圳建立一个cdn服务器,上面缓存住一些数据,深圳用户访问时先访问这个cdn服务器,如果服务器上有用户请求的数据就可以直接返回,这样速度就大大的提升了。
代售点优势:大部分请求在CDN边缘完成,起到了分流的作用,减轻源站的负载。
我们怎么知道用户的所在位置从而给他分配最佳的cdn节点呢。这就需要dns服务来进行定位了。
当我们在浏览器中输入一个域名时,首先需要将域名转换为ip地址,再将ip地址转换为mac地址,这样才能在网络上找到该服务器。当我们向dns服务器发起解析域名的请求时,dns服务器首先会查询自己的缓存中有没有该域名,如果缓存中存在该域名,则可以直接返回ip地址。如果缓存中没有,服务器则会以递归的方式层层访问。例如,我们要访问www.baidu.com,首先我们会先向全球13个根服务器发起请求,询问com域名的地址,然后再向负责com域名的名称服务器发送请求,找到baidu.com,这样层层递归,最终找到我们需要的ip地址。
DNS劫持又称为域名劫持,是一种恶意攻击,黑客或其他方通过使用流氓DNS服务器或其他策略来重定向用户,该策略更改了Internet用户被重定向到的IP地址。
DNS污染最常见的就是篡改host主机文件,通过篡改DNS主机文件ip地址和网址将不再一一对应,打开的网站将不是最初想要访问的网站。
DNS区域传输的时候使用TCP协议:
辅域名服务器会定时向主域名服务器进行查询以便了解数据是否变动。如有变动,会执行一次区域传送,进行数据同步。
域名解析时使用UDP协议:
客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过三次握手,这样DNS服务器负载更低,响应更快。
cdn中缓存了服务器上的部分资源。
当我们与DNS域名解析器解析的IP服务器建立TCP连接以后,此时向其发送请求时,我们可以在其中建立Nginx反向代理,可以实现
负载均衡
,屏蔽真实地址,安全管理
,解决跨域问题
,节约有效的IP资源
,减少web服务器压力,提高响应速度
Nginx是一个轻量级/高性能的反向代理Web服务器,他实现非常高效的反向代理、负载均衡
.
企业内部所有的网站共享一个在Internet中注册的IP地址,这些服务器分配私有地址,采用虚拟主机的方式对外提供服务。
反向代理就是通常所说的web服务器加速,它是一种通过在繁忙的web服务器和外部网络之间增加一个高速的web缓冲服务器来降低实际的web服务器的负载的一种技术。反向代理服务器会强制将外部网络对要代理的服务器的访问经过它,它会将从源服务器上获取到的静态内容缓存到本地,以便日后再收到同样的信息请求时,直接将本地缓存的内容发给客户端,减少后端web服务器的压力,提高响应速度。
请求的统一控制,包括设置权限,过滤规则等。
区分动态和静态可缓存内容。
实现负载均衡,内部可以采用多台服务器来组成服务器集群,外部还是可以采用一个地址访问。
解决ajax跨域问题。
作为真实服务器的缓存,解决瞬间负载量大的问题。
配置简单
占内存小,可实现高并发连接,处理响应快
处理动态页面很慢
因为他的事件处理机制:异步非阻塞事件处理机制(运用了epoll模型,提供了一个队列,排队解决)
nginx接收一个请求后,首先由listen和server_name指令匹配server模块,再匹配server模块里的location,location就是实际地址
server { # 第一个Server区块开始,表示一个独立的虚拟主机站点
listen 80; # 提供服务的端口,默认80
server_name localhost; # 提供服务的域名主机名
location / { # 第一个location区块开始
root html; # 站点的根目录,相当于Nginx的安装目录
index index.html index.htm; # 默认的首页文件,多个用空格分开
} # 第一个location区块结果
比如我们国内访问谷歌,直接访问访问不到,我们可以通过一个正向代理服务器,请求发到代理服,代理服务器能够访问谷歌,这样由代理去谷歌取到返回数据,再返回给我们,这样我们就能访问谷歌了
2.反向代理(Reverse Proxy)对外就表现为一个服务器。(反方代理就是请求统一被Nginx接收,nginx反向代理服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了)
实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器
[root@localhost ~]# tree /usr/local/nginx /usr/local/nginx ├── client_body_temp ├── conf # Nginx所有配置文件的目录 │ ├── fastcgi.conf # fastcgi相关参数的配置文件 │ ├── fastcgi.conf.default # fastcgi.conf的原始备份文件 │ ├── fastcgi_params # fastcgi的参数文件 │ ├── fastcgi_params.default │ ├── koi-utf │ ├── koi-win │ ├── mime.types # 媒体类型 │ ├── mime.types.default │ ├── nginx.conf # Nginx主配置文件,很重要!!! │ ├── nginx.conf.default │ ├── scgi_params # scgi相关参数文件 │ ├── scgi_params.default │ ├── uwsgi_params # uwsgi相关参数文件 │ ├── uwsgi_params.default │ └── win-utf ├── fastcgi_temp # fastcgi临时数据目录 ├── html # Nginx默认站点目录 │ ├── 50x.html # 错误页面优雅替代显示文件,例如当出现502错误时会调用此页面 │ └── index.html # 默认的首页文件 ├── logs # Nginx日志目录 │ ├── access.log # 访问日志文件 │ ├── error.log # 错误日志文件 │ └── nginx.pid # pid文件,Nginx进程启动后,会把所有进程的ID号写到此文件 ├── proxy_temp # 临时目录 ├── sbin # Nginx命令目录 │ └── nginx # Nginx的启动命令 ├── scgi_temp # 临时目录 └── uwsgi_temp # 临时目录
答: 首先当前我们的网络存在很多的恶意攻击,例如XSS,CSRF等等,我们客户端给服务器发送请求,访问服务器时,服务器需要对我们的请求进行相应的认证,同时对于我们客户端授予不同的权限,拥有相应的权限才能访问服务器,发送相应的请求信息。
jwt(Json web token) : 是为了在网络应用环境中传递声明而执行的一种基于JSON的开放标准(RFC 7519)
其中对应生成的token被设计成紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token可直接被用于认证,也可被加密。
JWT生成编码以后是以下的样子:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q
JWT由三个部分组成:
头部(header):
HMAC算法介绍:
完整的头部head信息就像下面的JSON:
{
'typ': 'JWT',
'alg': 'HS256'
}
然后我们会对头部信息进行加密,构成第一部分:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
载荷(payload):
载荷是存放有效信息的地方,有效信息包括三个部分:
其中,标准中注册的声明(建议但是不强制使用) :
公共的声明:
私有声明:
我们这里定义一个payload:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
进行加密处理以后,构成第二部分:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
签证(signature):
jwt的第三部分是一个签证信息,一般由三个部分组成:
UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q
其中密钥是保存在服务端的,服务端会根据这个密钥生成token和验证,所以必须要保存好!!!
最后一步签名的过程,实际上是对头部以及载荷内容进行签名。一般而言,加密算法对于不同的输入产生的输出总是不一样的。对于两个不同的输入,产生同样的输出的概率极其地小.
所以,如果有人对头部以及载荷的内容解码之后进行修改,再进行编码的话,那么新的头部和载荷的签名和之前的签名就将是不一样的。而且,如果不知道服务器加密的时候用的密钥的话,得出来的签名也一定会是不一样的.
服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次签名。那么服务器应用是怎么知道我们用的是哪一种算法呢?别忘了,我们在JWT的头部中已经用alg字段指明了我们的加密算法了。
如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token,返回一个HTTP 401 Unauthorized响应。
注意:
一般会在请求头中加入Authoriation,并加入Bearer标注:
fetch('api/user/1', {
headers: {
'Authorization': 'Bearer ' + token
}
})
服务端会验证token,如果验证通过就会返回相应的资源!
我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。
Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
它的流程如下所示:
这个token值必须在每次请求时传递给服务端,它应该保存在请求头中,另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了(Access-Control-Allow-Origin)
面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
我们系统发放的,其中带的信息是合法有效的;
我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。
Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
它的流程如下所示:
这个token值必须在每次请求时传递给服务端,它应该保存在请求头中,另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了(Access-Control-Allow-Origin)
面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
[外链图片转存中…(img-sZg1xEWd-1715766265510)]
[外链图片转存中…(img-LRTG82uZ-1715766265511)]
[外链图片转存中…(img-P3xZqJ7k-1715766265511)]
[外链图片转存中…(img-7jyPUXog-1715766265512)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。