Shopee HTTP面试总结

2,190 阅读11分钟

HTTP 缓存

首先都知道HTTP缓存都是从第二次请求开始的。

  1. 第一次发起请求后,服务器返回资源,并在response header中返回带Expires(http1.0)Cache-Control(http1.1)的字段,状态码为200
  2. 第二次发起请求后,强缓存命中则直接读取浏览器缓存,在network中显示的是from memory或者from disk,状态码为200。当浏览器的强缓存失效的时候或者请求头中设置了不走强缓存,并且在请求头中设置了If-Modified-Since(http1.0)或者If-None-Match(http1.1)的时候,会将这两个属性值到服务端去验证是否命中协商缓存,如果命中了协商缓存,会返回304状态码,加载浏览器缓存,并且响应头会设置Last-Modified或者ETag属性。
  3. 若强缓存和协商缓存都未命中,则服务器返回新的资源。

Q: 怎么设置不走强缓存?

  • 请求头设置Cache-Control: no-cache
    不会走强缓存了,每次请求都会询问服务端,但不妨碍协商缓存。
  • 请求头设置Cache-Control: no-store
    会让浏览器、服务器都不缓存,也就没有所谓的强缓存、协商缓存了。

Q: Cache-Control 的 public、 private 区别知道吗?

  • public:所有的内容都可以被缓存 ,包括浏览器和代理服务器, 如 CDN。
  • private:所有的内容只有浏览器可以缓存,代理服务器不能缓存,是默认值。

Q: from memory 和 from disk 区别知道吗?

  • from memory:一般是 字体、图片文件。(js脚本不一定)
  • from disk:一般是 css 文件。

HTTP 状态码

讲一些常见的HTTP状态码

  • 101: 在HTTP升级为WebSocket的时候,如果服务器同意变更,就会发送状态码 101。
  • 200:OK成功返回的状态码,有数据会放在响应体。
  • 204:NO Content成功返回的状态码,但响应头后没有 body 数据。
  • 301: Location 永久重定向。
  • 302: Location 临时重定向。
  • 304: Not Modified协商缓存。
  • 400: Bad Request 请求无效。
  • 401: Unauthorized 鉴权失败。
  • 403: Forbidden 禁止访问。
  • 404: Not Found 资源未找到。
  • 500: 服务端报错。 Q: 301 和 302 什么区别?
  • 301永久重定向是可以缓存的。(可以在Status Code后面看到 from disk/memory cache)
  • 302临时重定向没有缓存。

Q: 重定向会带上原来请求的数据吗?

  • 应该是可以带的。(暂定存疑)

HTTP 报文结构

请求报文和响应报文大致上都是起始行+头部+空行+实体

  • 起始行
    请求报文起始行请求方法 路径 HTTP版本
    响应报文起始行 HTTP版本 状态码 状态

  • 头部
    就是常见的那些请求头响应头字段。

  • 空行
    区分头部和实体。

  • 实体
    请求携带的数据或者响应返回的数据。

Q: 头部中间加一个空行会怎么样?

  • 空行后面的内容都是实体了。

Q: 常见的请求头、响应头有哪些

  • 如下

请求头、响应头

常见的请求头字段:

  • Host: 服务端的域名
  • Accept、Accept-Encoding、Accept-Language:与服务端的协商字段
  • Content-Type:浏览器请求体内容的类型
  • Content-Length:实体数据的字节长度。
  • Referer:请求的页面来源。
  • User-Agent:用户代理,一些厂商、设备、版本等信息。
  • Cookie:用户的Cookie信息。
  • 还有上面提到的缓存相关字段

常见的响应头字段:

  • Access-Control-Allow-Origin:指定哪些网站可以跨域源资源共享。
  • Access-Control-Allow-Methods:允许的http请求方法
  • Content-Type:服务端响应体内容的类型。
  • Content-Length:实体数据的字节长度,如果设置短了数据会丢失,设置长了会导致请求失败。
  • Set-Cookie:与请求头中的 Cookie 对应
  • 还有上面提到的缓存相关字段

Q: 请求头里的Referer是干什么用的?

  • 设置一些防盗链,比如直接在浏览器的地址栏中输入一个资源的URL地址,那么这种请求是不会包含Referer的。

Q: Content-Length是什么的长度?

  • 实体的传输字节长度。(实体长度和实体的传输长度是有区别,比如说gzip压缩下,消息实体长度是压缩前的长度,消息实体的传输长度是gzip压缩后的长度)

Q: 知道Transfer-Encoding: chunked这个字段吗?

  • 在数据内容不能确定,分块传输场景下使用。(无法在请求或者响应前明确指定Content-Length,所以Content-Length字段会被忽略不被发送)

Q: Cookie中有哪些属性?

  • Name:Cookie的名称。
  • Value: Cookie的值。
  • Domain: 指定Cookie的域名。
  • Path:指定Cookie所属的路径。(只有匹配上DomainPath才会附加Cookie)
  • Expires/Max-Age: 过期时间
  • Size:Cookie的大小
  • HttpOnly:禁止通过document.cookie等方式拿到Cookie。(缓解XSS攻击)
  • Secure: Cookie只能用https协议发送给服务器。
  • SameSite:可以有效缓解CSRF攻击。
    SameSite=None: 浏览器会在同站请求、跨站请求下继续发送Cookie。
    SameSite=Strict: 限制Cookie不能跨站发送,只在访问相同站点时发送Cookie。
    SameSite=Lax: 跨站请求时,如果是安全的HTTP方法情况会携带Cookie。

Q: 同源和同站的区别是什么?

  • 同源:scheme://ip/hostname:port一样表示同源。
  • 同站:二级域名.顶级域名一样表示同站。参考文章

安全

讲一下前端常见的一些安全问题以及怎么去预防。

  • XSS
    1、通过HTML内容攻击:模板渲染的时通过反射或者存储插入脚本。
    2、通过HTML属性攻击: 提前闭合一些属性,传入攻击代码。
    3、JS代码攻击:跟通过HTML内容攻击相似。
    4、获取Cookie信息:利用第三方脚本的document.cookie偷取。

    预防措施:
    1、对& < > " '这些进行转译。
    2、服务端设置白名单进行过滤。
    3、Set-Cookie时设置httpOnly标记,使JS无法获取Cookie的值。
    4、响应头设置Content-Security-Policy,不加载第三方脚本。

Q: HTML属性怎么攻击?

比如上传头像,本来保存的是一段url,然后页面通过<img src="url">渲染。
但是攻击者可能会传入 ' " onerror="alert('xxx')"'这样的字符串,这样页面渲染头像的时候就被攻击了。

Q: CSP除了在响应头里面设置,还可以在哪里设置?

可以在HTML里通过meta元素设置。

<meta http-equiv="Content-Security-Policy" content="default-src 'self';">

Q:CSP有哪些属性?
CSP属性说明

  • CSRF

    • 受害者登录a.com,并保留了登录凭证(Cookie)。
    • 攻击者引诱受害者访问了b.com。
    • b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
    • a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
    • a.com以受害者的名义执行了act=xx。
    • 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。

    预防措施:
    1、关键操作使用验证码
    2、通过Referer来检查请求的"源"。
    3、服务端Token校验机制。
    4、之前说到Cookie设置的SameSite

  • ClickJacking
    是一种视觉欺骗的手段,主要是一些类似iframe嵌入、图片覆盖、拖拽等类似方法攻击。

HTTPS 握手过程

1、先了解HTTPS的加密原理
2、再来抓包看握手过程

Cookie、Session、Token区别

  • Cookie只是实现Session的一种方案
    首先要明白Session和Cookie的主要目的就是为了弥补HTTP的无状态特性。

    1、用Session只需要在浏览器端保存一个id,实际上大量数据都是保存在服务端。
    2、如果全部用Cookie,数据量大的时候浏览器是没有那么多空间的。账户信息全在浏览器端,一旦被劫持全部信息都会泄露。而且每次请求的网络传输数据量也会变大。
    3、所以一般使用Session + Cookie方式来保持会话状态。

  • Token是一种认证方式
    1、用户登录成功,服务端通过一些参数组成加密生成秘钥返回给用户端。
    2、后续再次访问服务端,请求头都要带上这个Token秘钥来校验这个请求。(可以预防CSRF攻击)

浏览器跨域

不同源的请求就会被浏览器认为是跨域。

Q: 你们一般是通过什么方法解决跨域?

  • 一般是在node层做代理转发。

Q: 还有什么办法吗?

  • 通过script标签,jsonp传个回调函数,但是只支持GET请求。服务端返回的数据不是 JSON,而是 JavaScript,也就是说Content-Type 为 application/javascript,内容为callbackFunction(data) 。
  • 服务端设置CORS。

Q: 知道简单请求和非简单请求吗?
简单请求:

  • 请求方法为GET、HEAD、POST;
  • 且请求头范围为Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

非简单请求:

  • 不是简单请求就是非简单请求。

Q: 知道跨域中的简单请求和非简单请求流程吗?
简单请求会直接发出CORS请求。

  • 它会自动在请求头当中,添加一个Origin字段,服务器根据这个值,决定是否同意这次请求。
  • 如果Origin指定的源不在许可范围内,浏览器就会将响应拦截。
  • 如果Origin指定的源在许可范围内,响应头会多出Access-Control-Allow-OriginAccess-Control-Allow-CredentialsAccess-Control-Allow-Headers这几个字段。

非简单请求会在正式通信之前,增加一次OPTIONS请求,称为"预检"请求。

  • 服务器收到"预检"请求以后,检查OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段。
  • 如果服务器否定了"预检"请求,浏览器就会将响应拦截。
  • 如果确认允许了"预检"请求,会返回带有Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers的响应头字段。后续发起的CORS请求,就跟简单请求一样了。

Q: 如何避免发送多次OPTIONS预检请求?

  • 服务端设置Access-Control-Max-Age: xxx响应头(只对完全一样的url的缓存设置生效,单位为秒)

Q: 跨域请求怎么携带Cookie?

  • AJAX请求属性需要设置withCredentials:true
  • 服务端使用CORS协议解决跨域访问数据问题时,需要设置响应消息头Access-Control-Allow-Credentials:true

LocalStorage、SessionStorage区别

LocalStorage:

  • 同源的所有标签(tab)页之间共享数据。
  • 在浏览器重启甚至系统重启后仍然存在。

SessionStorage:

  • 只能存在于同一标签(tab)页的会话中,不同标签页不共享。
  • 它在同一标签页下的 iframe 之间是共享的(假如它们来自相同的源)。
  • 数据在页面刷新后仍然保留,但在关闭/重新打开浏览器标签页后不会被保留。

Q: localstorage存量过大时有什么解决方案吗?

  • 采用 IndexedDB 存储。

HTTP2 的优点

  • 头部压缩

    HTTP1.x 每次通讯(请求或响应)都会携带首部信息用于描述资源属性。
    HTTP2 在客户端和服务端会同时维护和更新一个包含之前见过的信息的索引列表。请求与响应首部的定义在基本没有变,只是所有首部键必须全部小写,而且请求报文起始行拆分成:method: :scheme: :authority: :path: 这些键值对

  • 二进制分帧

  • 多路复用

    HTTP1.x 基于请求-响应的模型,在同一个 TCP 长连接中,前面的请求没有得到响应,后面的请求就会被阻塞。并发连接虽然是一个解决办法,但是只是增加了TCP连接。而且这么做也有弊端,多条 TCP 连接会竞争有限的带宽,让真正优先级高的请求不能优先处理。

    HTTP2 基于二进制分帧,可以在共享一个TCP链接的基础上并行发送多个请求和响应。

  • 服务器推送

    通过服务端推送技术SSE来理解

Q: 头部压缩带来了什么优化?

  • 对于相同的数据,不再重新通过每次请求和响应发送。每个新的键值对要么追加到当前表的末尾,要么替换表中之前的值。这样可以减少每次通讯的数据量,使网络拥塞状态得以改善。

Q: 为什么HTTP1.x不能实现多路复用?

  • HTTP2 是基于二进制“帧”的协议,HTTP1.x 是基于“文本分割”解析的协议。

Q: keep-alive和多路复用区别是什么?

  • HTTP1.x 虽然可以采用keep-alive来解决复用TCP问题,但还是无法解决请求阻塞的问题。(半双工通信)
  • 多路复用就相当于是全双工通信了。

总结

这是我想到问到的HTTP题目,可能还有遗漏的,但是纰漏大概不是很多。面了1个半小时,有1个小时在聊HTTP这方面的东西。最终也是拿到了虾皮的offer,因为工作内容和薪资不满意,所以拒绝了offer。