前言
一年一度的校招来了,从网上总结各个大佬分享的面试题和经验,经过各种渠道查找资料,将网上的面试题做了下解析和自己的理解,如下就是我从网上整理的常问面试题和相关回答。希望自己面试顺利。
面试题
1、简单描述下TCP三次握手过程。
TCP属于TCP/IP协议簇四层模型中的传输层协议。
- 1、客户端发送一个带 SYN=1,Seq=X 的数据包到服务器端口(第一次握手,由浏览器发起,告诉服务器我要发送请求了)
- 2、服务器发回一个带 SYN=1, ACK=X+1, Seq=Y 的响应包以示传达确认信息(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧)
- 3、客户端再回传一个带 ACK=Y+1, Seq=Z 的数据包,代表“握手结束”(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)
为什么是三次握手?因为通过三次的话,客户端和服务端均能确认对方具备发送和接受数据的能力。
2、网络安全,讲讲XSS、CSRF的原理,黑客是如何利用这些漏洞的?
XSS是指跨站脚本,主要是因为在浏览器中<Script>
可以跨域加载脚本,合理利用如JSONP。
XSS是指在正常的输入内容处输入不合理内容,如<script>
、<iframe>
等,然后黑客可以通过这些加载恶意代码,获取用户Cookie等。XSS分为反射型、存储型、DOM型漏洞,其中前两者属于服务端的安全漏洞,后一种属于前端安全漏洞。
CSRF全称跨站请求伪造,是一种劫持受信任用户向服务器发送非预期请求的攻击方式。
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
3、XSS如何防御,交给前端做还是后端做,怎么做?
前端和后端都要做相应的防御措施。
- HttpOnly防止劫取Cookie,这个是防止javascript获取cookie的方法,并不能防止xss攻击,但是可以防止xss攻击后的cookie劫持攻击,这部分主要在前端实现。
- 输入检查,不要相信用户的任何输入,前端和后端都做相应的输入检查,要对特殊字符进行过滤、检查和转译。
- 输出检查,后端做好输出检查,一般来说,除富文本的输出外,在变量输出到 HTML 页面时,可以使用编码或转义的方式来防御 XSS 攻击。
- 输入内容长度限制,对于不受信任的输入,都应该限定一个合理的长度。虽然无法完全防止 XSS 发生,但可以增加 XSS 攻击的难度。
- 验证码,防止脚本冒充用户提交危险操作。
4、CSRF如何防御?同源策略解决了什么问题?
CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。
具体防护措施如下:
- 同源检查,在后端禁止外域访问,浏览器前端会携带Origin和Referer两个首部属性,并且不能由前端自定义内容。后端可以通过解析这两个Header中的域名,确定请求的来源域。
- CSRF Token,服务端生成一串token并传给前端,前端在发起get或post请求的时候将token携带在里面。
- 双重Cookie,利用CSRF不能获取原网站的Cookie特点,在URL里面携带Cookie,服务端在收到请求后对比URL里的Cookie和请求头里的Cookie是否一致。
所以同源策略其实是解决了跨域安全问题。同源策略是指“协议+域名+端口”三者必须相同,即便两个不同的域名指向同一个ip地址,也非同源。
5、http请求跨域问题,你知道哪些解决跨域的方法?
在同源策略下,一个域下的文档或脚本试图去请求另一个域下的资源时会被浏览器禁止,从而限制ajax请求,Cookie、localStorage 和 IndexDB 无法读取,DOM和JS对象无法获得。在前后端分离的使用场景中,跨域请求需要被满足。
解决跨域问题,可以从前端和后端两个方向入手。
前端常用方案:
1、 采用JSONP,需要后端配合
其实就是用JS构建script请求数据,一般后端返回值如:
handleCallback({"status": true, "user": "admin"});
复制代码
然后我们在已存在的JS中实现这么一个回调函数
// 回调执行函数
function handleCallback(res) {
alert(JSON.stringify(res));
}
复制代码
2、document.domain + iframe跨域
适合子域不同但主域相同的情况(一级域名相同二级域名不同的情况),父窗口设置document.domain = 'domain.com'
; 使用<iframe>
加载子窗口内容,然后在子窗口的全局作用域设置document.domain = 'domain.com'
;,这样子窗口可以使用window.parent
获取父窗口的变量
3、location.hash + iframe跨域
利用<iframe>
三层嵌套,比如a域与b域是不同的域,想要相互通信,可以利用c域来实现(其中,c域与a域同域),不同域之间,可以利用location.hash
来通信,相同域之间直接js即可。
具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
4、postMessage跨域 —— HTML5新增
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题: a.) 页面和其打开的新窗口的数据传递 b.) 多窗口之间消息传递 c.) 页面与嵌套的iframe消息传递 d.) 上面三个场景的跨域数据传递
用法:postMessage(data,origin)方法接受两个参数 data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。 origin: 协议+主机+端口号,也可以设置为”*”,表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/“。
后端常用方案:
1、设置允许跨域头部信息
前端同源策略中,首先浏览器发起跨域请求->服务端判断Origin和Refer是否被允许->浏览器收到服务端返回的结果,如果是不被允许的跨域请求则报错。
所以只需要服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
2、利用中间服务***,比如利用Nginx***转发请求、或者其他中间服务***。
3、Websocket支持跨域
6、说说http缓存和CDN原理?
HTTP缓存有两种形式,分别是强制缓存和对比缓存,缓存包含缓存数据和缓存规则,缓存规则由服务端响应报文在首部的字段中设置。
强制缓存:
强制缓存的规则,由服务端返回的响应报文中这两个字段确定:
字段名 | 解释 |
---|---|
Expires | HTTP 1.0时期,用来返回到期时间,客户端下次请求时判断是否到期,未到期就使用缓存 |
Cache-Control | Cache-Control 是HTTP1.1最重要的规则。常见的取值有private、public、no-cache、max-age,no-store,默认为private。其中max-age=xxx表示缓存的内容将在 xxx 秒后失效 |
对比缓存:
对比缓存的规则有两种,一种是基于修改时间,一种是基于唯一标识,其中唯一标识比修改时间的规则优先级更高。
基于修改时间:
网络状态 | 字段名 | 解释 |
---|---|---|
响应 | Last-Modified | 服务器响应时,告诉浏览器当前返回的数据的最后修改时间 |
请求 | If-Modified-Since | 服务器接收到请求之后判断是否存在新的资源修改,如果有新的资源修改,那就返回200状态码,浏览器重新请求资源,否则返回304状态码,浏览器使用缓存 |
基于唯一标识:
网络状态 | 字段名 | 解释 |
---|---|---|
响应 | Etag | 服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。 |
请求 | If-None-Match | 服务器收到与被请求资源的服务端唯一标识进行比对,不同,说明资源被改动过,则响应整片资源内容,返回状态码200;相同,说明资源无新修改,则返回304状态码,告知浏览器继续使用缓存 |
CDN原理简单叙述
CDN是一种公共服务,他本身有很多台位于不同地域、接入不同运营商的服务器,而所谓的使用CDN实质上就是让CDN作为网站的门面,用户访问到的是CDN服务器,而不是直接访问到网站。由于CDN内部对TCP的优化、对静态资源的缓存、预取,加上用户访问CDN时,会被智能地分配到最近的节点,降低大量延迟,让访问速度可以得到很大提升。
具体举个例子:
用户在首次访问 https://assets-cdn.github.com/pinned-octocat.svg
, 假设不委托local DNS服务器递归查询,会经历以下几个过程
1、浏览器检查本地有没有这个东东的有效缓存,有则使用缓存,没有有效缓存则进行对assets-cdn.github.com
的DNS查询,获得一个CNAME记录, github.map.fastly.net
,值得注意的是,多个加速域名可以解析到同一个CNAME,CDN回源和缓存的时候考虑到了hostname,👍;
2、进行对github.map.fastly.net
的DNS查询,获得一个A/AAAA记录,给出地址103.245.222.133(视网站不同返回的不一样,可以有多个), 这一步对CDN来说时十分重要的,它给出了离用户最近的边缘节点;浏览器选一个返回的地址,然后进行真正的http请求,开始向103.245.222.133握手,握手完了把http请求头也发给了该边缘服务器;
3、边缘服务器检查自己的cache里面有没有https://assets-cdn.github.com/pinned-octocat.svg
这个资源,有则返回给用户,如果没有,向CDN中心服务器发起请求;
4、CDN中心服务器检查自己的cache里面有没有这个资源,有则返回给边缘服务器,没有则回源(回源是指取访问该资源的原服务器);中心服务器发现客户配置了github.map.fastly.net
的回源地址(这个只有cdn会知道,假设是xxx.xxx.xxx.xxx),就把http请求发到源站地址上,源站返回后返回给请求方;
7、http和https的区别,https有什么好处,https的通信过程,https是如何做到“安全”的?
https不是一个新的协议,它只是http协议身披一层SSL(Secure Socket Layer,安全套接层)协议,SSL这层协议存在于应用层(http层)到TCP层之间。
区别如下:
- https协议需要向CA机构申请证书
- http传输的信息是明文传输,https则是加密传输
- http与https使用不同的连接方式,默认端口也不一样,http默认80,https默认443
- http连接很简单,无状态;https是由SSL + HTTP协议构建的可进行加密传输、身份认证的网络协议,更加安全可靠。
https工作原理:
8、http2了解吗?http2和http1的区别和好处?http2头部压缩的原理?
【区别】
从传输方式上,http2采用二进制传输,取代了HTTP1.x的文本格式,二进制格式解析更高效。
从传输机制上,在http/1.0时代,每次请求都会创建一次TCP连接,占用大量时间与服务资源,在http/1.1版本中,默认开启了Connection:keep-alive
,采用单路长连接复用模式,解决了多次TCP连接的问题,因为是串行文件传输所以同一个TCP连接里的HTTP请求必须排队等待上一个完成。
在http2中,采用多路复用模式,有两个概念就是流和帧,帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。多路复用,就是在一个TCP连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免HTTP旧版本中的队头阻塞问题,极大的提高传输性能。
简单来说http2的特点就是:
1.同域名下所有通信都在单个连接上完成,消除了因多个TCP连接而带来的延时和内存消耗。
2.单个连接上可以并行交错的请求和响应,之间互不干扰。
【http2头部压缩原理】
HTTP请求和响应都是由「状态行、请求/响应头部、消息主体」三部分组成。一般而言,消息主体都会经过 gzip 压缩,或者本身传输的就是压缩过后的二进制文件(例如图片、音频),但状态行和头部却没有经过任何压缩,直接以纯文本传输。这在大量的http传输中,消耗的流量会越来越多。
头部压缩需要在支持 HTTP/2 的浏览器和服务端之间:
- 维护一份相同的静态字典(Static Table),包含常见的头部名称,以及特别常见的头部名称与值的组合;
- 维护一份相同的动态字典(Dynamic Table),可以动态地添加内容;
- 支持基于静态哈夫曼码表的哈夫曼编码(Huffman Coding);
静态字典的作用有两个:
1)对于完全匹配的头部键值对,例如 :method: GET,可以直接使用一个字符表示;
2)对于头部名称可以匹配的键值对,例如 cookie: xxxxxxx,可以将名称使用一个字符表示。
9、你知道哪些Http头部?怎么与服务端保持长连接?
常见的首部:
请求首部 | 作用(请求报文专用) |
---|---|
Accept | 能正确接收的媒体类型:application/json text/plain |
Accept-Encoding | 能正确接收的编码格式列表:gzip deflate |
Authorization | 客户端认证信息,一般存token用 |
Cookie | 发送给服务器的Cookie信息 |
Host | 服务器的域名,用于区分单台服务器多个域名的虚拟主机,是HTTP/1.1唯一必须包含的字段。 |
If-Match | 两端资源标记比较,只有判断条件为真服务端才会接受请求 |
If-Modified-Since | 本地资源未修改返回 304(比较时间) |
If-None-Match | 本地资源未修改返回 304(比较标记) |
User-Agent | 客户端信息 |
Max-Forwards | 限制可被***及网关转发的次数 |
Proxy-Authorization | 向***服务器发送验证信息 |
Range | 请求某个内容的一部分,配合If-Range使用 |
Referer | 请求发起页面的原始URI |
Expires | 内容的过期时间 |
Last_modified | 内容的最后修改时间 |
ETag | 资源标识,资源发生变化时标识也会发生改变 |
Location | 客户端重定向到某个 URL |
Server | 服务器名字:Apache Nginx |
Set-Cookie | 需要存在客户端的信息,一般用于识别用户身份 |
Allow | 资源的正确请求方式:GET HEAD POST |
Content-Length | request body 长度(即实体主体的大小) |
Content-MD5 | Base64加密格式的内容 MD5检验值 |
Content-Range | 响应主体的内容范围 |
Content-Type | 内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求) |
Expires | 内容的过期时间 |
保持长连接,在http/1.1中默认开启Connection:keep-alive
,其中服务端响应首部Keep-alive:timeout=5, max=1000
10、你了解哪些http请求方法,分别有哪些作用和不同?
方法 | 说明 |
---|---|
GET | GET请求会显示请求指定的资源。一般来说GET方法应该只用于数据的读取,而不应当用于会产生副作用的非幂等的操作中。它期望的应该是而且应该是安全的和幂等的。这里的安全指的是,请求不会影响到资源的状态。 |
HEAD | HEAD方法与GET方法一样,都是向服务器发出指定资源的请求。但是,服务器在响应HEAD请求时不会回传资源的内容部分,即:响应主体。这样,我们可以不传输全部内容的情况下,就可以获取服务器的响应头信息。HEAD方法常被用于客户端查看服务器的性能。 |
POST | POST请求会 向指定资源提交数据,请求服务器进行处理,如:表单数据提交、文件上传等,请求数据会被包含在请求体中。POST方法是非幂等的方法,因为这个请求可能会创建新的资源或/和修改现有资源。 |
PUT | PUT请求会身向指定资源位置上传其最新内容,PUT方法是幂等的方法。通过该方法客户端可以将指定资源的最新数据传送给服务器取代指定的资源的内容。 |
DELETE | DELETE请求用于请求服务器删除所请求URI(统一资源标识符,Uniform Resource Identifier)所标识的资源。DELETE请求后指定资源会被删除,DELETE方法也是幂等的。 |
CONNECT | CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的***服务器。通常用于SSL加密服务器的链接与非加密的HTTP***服务器的通信。 |
OPTIONS | OPTIONS请求与HEAD类似,一般也是用于客户端查看服务器的性能。 这个方***请求服务器返回该资源所支持的所有HTTP请求方法,该方***用'*'来代替资源名称,向服务器发送OPTIONS请求,可以测试服务器功能是否正常。JavaScript的XMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限。 |
TRACE | TRACE请求服务器回显其收到的请求信息,该方法主要用于HTTP请求的测试或诊断。 |
PATCH | PATCH方法出现的较晚,它在2010年的RFC 5789标准中被定义。PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:1.PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。2.当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新。 |
名词解释:
幂等:对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的。
11、HTTP状态码都有哪些?代表什么意思?
2XX | 成功(表明请求被正常处理了) |
---|---|
200 | OK,表示从客户端发来的请求在服务器端被正确处理 |
204 | No content,表示请求成功,但响应报文不含实体的主体部分 |
206 | Partial Content,进行范围请求成功,返回部分内容 |
3XX | 重定向(表明浏览器要执行特殊处理) |
---|---|
301 | moved permanently,永久性重定向,表示资源已被分配了新的 URL |
302 | found,临时性重定向,表示资源临时被分配了新的 URL |
303 | see other,表示资源存在着另一个 URL,应使用 GET 方法获取资源(对于301/302/303响应,几乎所有浏览器都会删除报文主体并自动用GET重新请求) |
304 | not modified,表示服务器允许访问资源,但请求未满足条件的情况(与重定向无关) |
307 | temporary redirect,临时重定向,和302含义类似,但是期望客户端保持请求方法不变向新的地址发出请求 |
4XX | 客户端错误 |
---|---|
400 | bad request,请求报文存在语法错误 |
401 | unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息 |
403 | forbidden,表示对请求资源的访问被服务器拒绝,可在实体主体部分返回原因描述 |
404 | not found,表示在服务器上没有找到请求的资源 |
5XX | 服务端错误 |
---|---|
500 | internal sever error,表示服务器端在执行请求时发生了错误 |
501 | Not Implemented,表示服务器不支持当前请求所需要的某个功能 |
503 | service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求 |
12、请说说GET与POST的区别?
其实,POST与GET都是HTTP通信中传输的,从这个层面来讲,其区别在于GET只产生一个TCP数据包,POST产生两个(第一个是浏览器先发送header,服务器响应100之后,浏览器再将data发出去)。而且并不是所有的浏览器在POST请求时都产生两个TCP数据包,Firefox就只有一次。
网上常见的GET与POST的区别,其实是在浏览器/服务器层次的理解:
- GET在浏览器回退时是无害的,而POST会再次提交请求;
- GET请求会被浏览器主动cache,而POST不会,除非手动设置;
- GET请求只能进行url编码,而POST支持多种编码方式;
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留;
- GET请求在URL中传送的参数是有长度限制的(不同浏览器长度限制不同,IE最短为2083个字符),而POST没有;
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制;
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息;
- GET参数通过URL传递,POST放在Request body中。