Skip to content

简述 HTTPS 加密过程

20251208194017

HTTPS 使用 TLS/SSL 协议进行加密,主要包含以下步骤:

1.客户端发起请求

  • 发送支持的加密算法列表
  • 发送随机数 Client Random

2.服务器回应

  • 选择加密算法
  • 发送数字证书(包含公钥)
  • 发送随机数 Server Random

3.客户端验证证书

  • 验证证书是否由可信 CA 签发
  • 验证证书域名是否匹配
  • 验证证书是否在有效期内

4.生成会话密钥

  • 客户端生成随机数 Pre-master secret
  • 使用服务器公钥加密 Pre-master secret
  • 客户端和服务器都通过三个随机数生成会话密钥 (Client Random + Server Random + Pre-master secret)

5.开始加密通信

  • 双方使用会话密钥进行对称加密通信
  • 保证通信内容的机密性和完整性

特点:

  • 采用混合加密:非对称加密传输密钥,对称加密传输数据
  • 数字证书保证服务器身份可信
  • 具有防篡改和不可否认性

扩展:图解SSL/TLS协议

TCP 是如何建立连接的,三次握手,四次挥手

20251208194623

三次握手

  • 客户端向服务端发送建立连接请求,客户端进入 SYN-SEND 状态
  • 服务端收到建立连接请求后,向客户端发送一个应答,服务端进入 SYN-RECEIVED 状态
  • 客户端接收到应答后,向服务端发送确认接收到应答,客户端进入 ESTABLISHED 状态

20251208194638

四次挥手

  • 客户端向服务端发送断开连接请求
  • 服务端收到断开连接请求后,告诉应用层去释放 tcp 连接
  • 服务端向客户端发送最后一个数据包 FINBIT ,服务端进入 LAST-ACK 状态
  • 客户端收到服务端的断开连接请求后,向服务端确认应答

三次握手四次挥手,客户端都是主动方,服务端都是被动方。在状态方面:三次握手的客户端和服务端都是由原来的 closed 变为 established,四次挥手的客户端和服务端都是由原来的 established 变为 closed。

HTTP 几个版本的区别

HTTP/0.9

  • 仅支持 GET 请求,无请求头和请求体
  • 只能传输 HTML 文件,返回 ASCII 字符流
  • 无响应头

缺点:功能极其有限

HTTP/1.0 多类型支持

  • 支持多种文件类型(不限于 ASCII)
  • 引入请求头和响应头(key-value 形式)
  • 每个请求都需要建立新的 TCP 连接

缺点:频繁连接导致性能开销

HTTP/1.1 持久连接

  • 引入持久连接(keep-alive): 一个 TCP 连接可传输多个 HTTP 请求
  • 默认开启 keep-alive,通常限制 6-8 个并发连接
  • 引入 Host 字段,支持虚拟主机
  • 引入 Chunk transfer 机制处理动态内容长度

缺点:存在队头阻塞问题(前面的请求阻塞后续请求)

HTTP/2.0 多路复用

  • 一个域名仅使用一个 TCP 长连接
  • 引入二进制分帧层,实现多路复用(并行传输请求)
  • 支持请求优先级
  • 强制使用 HTTPS(HTTP + TLS 加密)

仍依赖 TCP,存在 TCP 队头阻塞问题

HTTP/3.0 QUIC 协议

  • 基于 UDP 协议而非 TCP
  • 实现了类似 TCP 的流量控制和可靠传输
  • 继承 TLS 加密
  • 多路费用
  • 解决 TCP 对头阻塞问题

HTTP 常见的状态码

1. 2xx 成功状态码

重点解析

  • 200 OK:最基础的成功状态码,表示请求完全成功。
  • 204 No Content:成功但无返回数据,适用于不需要返回内容的操作(如 DELETE)。
  • 205 Reset Content:要求客户端重置当前视图(如提交表单后清空输入框)。
  • 206 Partial Content:支持分块传输(如视频流、大文件下载)。

实际场景

  • 204:删除资源后,服务器只需确认成功,无需返回数据。
  • 206:浏览器下载大文件时,通过 Range 头实现断点续传,服务器返回 206 和部分内容。

2. 3xx 重定向状态码

重点解析

  • 301 vs 302
    • 301:永久重定向,搜索引擎会更新链接到新地址。
    • 302:临时重定向,搜索引擎仍保留原地址。
  • 303:强制客户端用 GET 方法访问新地址(避免 POST 重复提交)。
  • 304:协商缓存,通过 ETagLast-Modified 判断资源是否修改。

实际场景

  • 301:网站域名更换,旧域名永久跳转到新域名。
  • 302:用户未登录时临时跳转到登录页。
  • 304:浏览器缓存未过期,直接使用本地资源,减少服务器压力。

3. 4xx 客户端错误状态码

重点解析

  • 400:请求语法错误(如 JSON 格式错误)。
  • 401 vs 403
    • 401:未认证(如未登录或 token 失效)。
    • 403:已认证但无权限(如普通用户访问管理员接口)。
  • 404:资源不存在(可能是 URL 拼写错误)。

实际场景

  • 401:前端未携带 token 访问需要认证的接口。
  • 403:用户尝试删除他人数据时被拒绝。
  • 404:输入错误的 API 路径。

4. 5xx 服务端错误状态码

重点解析

  • 500:服务器内部错误(如代码抛出未捕获的异常)。
  • 501:服务器不支持请求的功能(如调用了未实现的 API)。
  • 503:服务不可用(如服务器过载或维护)。

实际场景

  • 500:数据库连接失败导致服务崩溃。
  • 503:电商大促时服务器流量激增,暂时限流。

面试加分点

  1. 缓存机制

    • 提到 304 时,可以展开说:
      • 浏览器通过 If-Modified-Since(基于时间)或 If-None-Match(基于 ETag)发起条件请求。
      • 服务器比对后决定返回 304200
  2. 安全设计

    • 403 可以结合敏感词过滤或权限系统设计。
    • 401 需提到 JWTOAuth 认证流程。
  3. 性能优化

    • 206 用于优化大文件传输。
    • 301 减少重复跳转的开销。
  4. 高可用

    • 如何避免 503
      • 答案:负载均衡、服务降级、限流策略(如令牌桶)。

模拟面试问题

  1. 问题:用户登录后访问某个接口返回 403,可能是什么原因?
    回答:可能是权限不足(如普通用户访问管理员接口),或请求被风控系统拦截(如敏感操作)。

  2. 问题:如何实现文件的断点续传?
    回答:客户端通过 Range 头指定下载范围,服务器返回 206 和部分内容,并支持 ETag 校验文件一致性。

  3. 问题304 是如何减少带宽消耗的?
    回答:浏览器缓存资源后,下次请求携带 If-None-MatchETag),若资源未修改,服务器返回 304,浏览器直接使用缓存。

HTTP 常见 Header

请求头

  • accept: text/html 告诉服务端我期望接收到一个html的文件
  • accept-encoding: gzip, deflate, br 告诉服务端以这种方式压缩
  • accept-language: zh-CN 告诉服务端以中文的格式返回
  • authorization: 告诉服务端授权信息
  • cookie: 告诉服务端客户端存储的 cookie
  • origin: 告诉服务端请求的来源

响应头

  • content-encoding: br 告诉浏览器压缩方式是br
  • content-type: text/html; charset=utf-8 告诉浏览器以这种方式,编码加载
  • cache-control: 告诉浏览器缓存策略
  • expires: 告诉浏览器缓存过期时间
  • set-cookie: 告诉浏览器设置 cookie
  • access-control-allow-origin: * 告诉浏览器允许跨域

URL 包含哪些部分

  • 协议
  • 域名
  • 端口号
  • 路径
  • 查询参数
  • 锚点

Ajax Fetch Axios 三者有什么区别

Ajax、Fetch 和 Axios 都是用于发送 HTTP 请求的技术,但有以下区别:

Ajax (Asynchronous JavaScript and XML)

  • 是一种技术统称,不是具体的 API
  • 最常用的实现是 XMLHttpRequest (XHR)
  • 写法比较繁琐,需要手动处理各种状态
  • 回调地狱问题
  • 不支持 Promise

Fetch

  • 浏览器原生 API
  • 基于 Promise
  • 更简洁的写法
  • 不需要额外引入
  • 只对网络请求报错,对 400、500 都当做成功的请求
  • 默认不带 cookie
  • 不支持请求超时控制
  • 不支持请求取消
  • 不支持请求进度监控

Axios

  • 第三方库,需要额外引入
  • 基于 Promise
  • 支持浏览器和 Node.js
  • 请求/响应拦截器
  • 自动转换 JSON 数据
  • 客户端支持防止 XSRF
  • 支持请求取消
  • 支持请求超时控制
  • 支持请求进度监控
  • 支持并发请求
  • 自动转换请求和响应数据

Fetch 和 XMLHTTPRequest 有什么区别

Fetch 和 XMLHTTPRequest 都是浏览器提供的 API,用于发送 HTTP 请求,但有以下区别:

语法和使用

  • Fetch 基于 Promise,代码更简洁优雅
  • XHR 使用回调函数,容易产生回调地狱
  • Fetch 的 API 设计更简单现代
  • XHR 的 API 设计较老,使用相对复杂

功能特性

  • Fetch 默认不发送 cookies,需要配置 credentials
  • XHR 默认发送 cookies
  • Fetch 不能监听上传进度
  • XHR 可以监听上传和下载进度
  • Fetch 不能直接取消请求(需要 AbortController)
  • XHR 可以通过 abort() 直接取消请求

错误处理

  • Fetch 只有网络错误才会 reject,HTTP 错误码不会导致 reject
  • XHR 可以处理所有类型的错误,包括 HTTP 错误码

浏览器支持

  • Fetch 是现代浏览器标准 API
  • XHR 有更好的浏览器兼容性,包括旧版本

什么是 Restful API

RESTful API 是一种软件架构风格,用于设计网络应用程序的接口。主要特点:

资源导向

  • 使用 URL 定位资源
  • 每个资源都有唯一的 URL
  • 资源可以有多种表现形式(如 JSON、XML)

HTTP 方法对应操作

  • GET:获取资源
  • POST:创建资源
  • PUT:更新资源(完整更新)
  • PATCH:更新资源(部分更新)
  • DELETE:删除资源

无状态

  • 服务器不保存客户端状态
  • 每个请求包含所需的所有信息
  • 有利于横向扩展

统一接口

  • 使用标准的 HTTP 方法
  • 使用标准的 HTTP 状态码
  • 返回格式一致(通常是 JSON)

什么是 GraphQL

GraphQL 是一种用于 API 的查询语言和运行时,由 Facebook 开发。主要特点:

查询灵活性

  • 客户端可以精确指定需要哪些数据
  • 可以在一个请求中获取多个资源
  • 避免了传统 REST API 的过度获取和获取不足问题

类型系统

  • 强类型的 Schema 定义
  • 自动生成文档
  • 开发时有更好的类型提示

单个端点

  • 只需要一个 API 端点
  • 所有查询都发送到同一个地址
  • 通过查询语句区分不同的操作

主要操作类型

  • Query:获取数据
  • Mutation:修改数据
  • Subscription:实时数据订阅

优点

  • 减少网络请求
  • 避免版本化问题
  • 强类型保障
  • 更好的开发体验

缺点

  • 学习成本较高
  • 缓存较为复杂
  • 服务端实现复杂度增加

Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据。

主要特点

  • 由服务器生成,浏览器进行存储
  • 每次请求时会自动携带对应域名下的 cookie
  • 可设置过期时间
  • 默认情况下随着浏览器关闭而删除(会话 cookie)

常用属性

  • name:cookie 名称
  • value:cookie 值
  • domain:指定 cookie 所属域名
  • path:指定 cookie 所属路径
  • expires/max-age:过期时间
  • secure:只在 HTTPS 下传输
  • httpOnly:禁止 JS 访问
  • sameSite:跨站点请求限制

使用场景

  • 会话状态管理(用户登录状态、购物车等)
  • 个性化设置(用户偏好、主题等)
  • 浏览器行为跟踪(分析用户行为等)

限制

  • 大小限制:通常为 4KB
  • 数量限制:每个域名下的 cookie 数量有限
  • 安全性:明文传输(除非使用 HTTPS)
  • 作用域:只能在所属域名下使用

主要原因是保护用户隐私和安全:

隐私问题

  • 第三方 Cookie 可以跨站点追踪用户行为
  • 广告商可以构建用户画像和浏览历史
  • 用户数据可能被未经授权收集和使用

安全风险

  • 增加 CSRF(跨站请求伪造)攻击风险
  • 可能被用于会话劫持
  • 恶意网站可能滥用第三方 Cookie

技术影响

  • Safari 和 Firefox 已默认禁用第三方 Cookie
  • Chrome 计划在 2024 年完全禁用第三方 Cookie
  • 替代方案:
    • First-Party Cookie
    • localStorage
    • Privacy Sandbox
    • FLoC (Federated Learning of Cohorts)

如何理解 Session

Session 是服务器端的会话管理机制:

基本概念

  • 服务器为每个用户创建的临时会话存储空间
  • 用于保存用户的会话状态
  • 通过 SessionID 来识别不同用户
  • SessionID 通常保存在 Cookie 中

工作流程

  • 用户首次访问服务器时,服务器创建 Session 并生成 SessionID
  • 服务器将 SessionID 通过 Cookie 发送给客户端
  • 客户端后续请求会自动携带包含 SessionID 的 Cookie
  • 服务器通过 SessionID 找到对应 Session 并识别用户

特点

  • 安全性较高:敏感数据存储在服务器
  • 服务器负载较大:需要存储所有用户的 Session
  • 依赖 Cookie:通常需要 Cookie 来存储 SessionID
  • 集群问题:需要考虑 Session 共享

使用场景

  • 用户登录状态管理
  • 购物车
  • 权限验证
  • 表单验证
  • 存储位置:Session 在服务器,Cookie 在客户端
  • 安全性:Session 较安全,Cookie 相对不安全
  • 存储容量:Session 容量较大,Cookie 通常限制 4KB
  • 性能:Session 消耗服务器资源,Cookie 消耗带宽资源

什么是 JWT 描述它的工作过程

JWT (JSON Web Token) 是一种开放标准,用于在各方之间安全地传输信息。

组成部分(用 . 分隔的三部分)

  • Header(头部):指定加密算法和令牌类型
  • Payload(负载):包含声明(claims)的实际数据
  • Signature(签名):对前两部分的签名,用于验证消息未被篡改

工作流程

1.用户登录成功后,服务器创建 JWT

  • 设置 Header 和 Payload
  • 使用密钥生成签名
  • 将三部分组合成 token

2.服务器将 token 返回给客户端

  • 客户端存储在 localStorage 或 cookie 中

3.客户端后续请求携带 token

  • 通常放在 Authorization header
  • 格式:Bearer <token>

4.服务器验证 token

  • 检查签名是否有效
  • 验证是否过期
  • 验证其他声明(claims)

特点

  • 无状态:服务器不需要存储会话信息
  • 可扩展:负载部分可以包含自定义数据
  • 跨域友好:可以在不同域名下使用
  • 性能好:验证在服务端完成,不需要查询数据库

安全考虑

  • 不要在 payload 中存储敏感信息
  • 设置合理的过期时间
  • 使用 HTTPS 传输
  • 妥善保管签名密钥

JWT 如何自动更新 token

JWT token 自动更新主要有以下几种方案:

双 token 机制

  • access token:短期令牌,用于接口认证
  • refresh token:长期令牌,用于刷新 access token
  • 优点:安全性高,即使 access token 泄露影响有限
  • 缺点:实现相对复杂,需要额外存储 refresh token

工作流程

  • 用户登录后获取 access token 和 refresh token
  • 使用 access token 访问接口
  • access token 过期时,使用 refresh token 获取新的 access token
  • refresh token 过期时,需要重新登录
js
// 前端示例代码
async function request(url, options) {
  try {
    const res = await fetch(url, {
      ...options,
      headers: {
        Authorization: `Bearer ${getAccessToken()}`,
      },
    })

    if (res.status === 401) {
      // access token 过期,尝试刷新
      const newToken = await refreshToken()
      if (newToken) {
        // 使用新 token 重试请求
        return request(url, options)
      } else {
        // refresh token 也过期,跳转登录
        redirectToLogin()
      }
    }

    return res
  } catch (error) {
    console.error(error)
  }
}

滑动过期机制

  • 每次请求都刷新 token 过期时间
  • 类似于会话超时机制
  • 优点:实现简单,用户体验好
  • 缺点:安全性相对较低

无感刷新机制

在 token 即将过期时自动刷新 可以通过定时器或请求拦截器实现 优点:用户无感知,体验好 缺点:需要处理并发请求的问题

最佳实践

  • 根据业务安全需求选择合适的方案
  • access token 过期时间不宜过长(如 2 小时)
  • refresh token 过期时间可以较长(如 7 天)
  • 重要操作仍需要二次验证
  • 考虑 token 注销机制

什么是 SSO 单点登录,描述它的工作过程

SSO (Single Sign On) 单点登录是一种身份验证机制,允许用户使用一组凭证访问多个相关但独立的系统。

基本概念

  • 一次登录,全局通用
  • 多个子系统共享用户会话
  • 统一的认证中心
  • 提高用户体验和安全性

工作流程

用户首次访问系统

  • 用户访问系统 A
  • 系统 A 检查无登录状态
  • 重定向到 SSO 认证中心
  • 带上系统 A 的地址作为参数

SSO 认证中心处理

  • 检查用户是否已登录 SSO
  • 未登录则显示登录页面
  • 用户输入账号密码
  • 认证中心验证身份

回到系统 A

  • SSO 生成票据(ticket)
  • 重定向回系统 A
  • 带上票据参数
  • 系统 A 验证票据
  • 创建本地会话

访问系统 B

  • 用户访问系统 B
  • 系统 B 检查无登录状态
  • 重定向到 SSO 认证中心
  • SSO 发现用户已登录
  • 直接生成票据返回
  • 系统 B 验证票据
  • 创建本地会话

实现方式

  • 基于 Cookie
  • 基于 Token
  • 基于 SAML
  • 基于 OAuth
  • 基于 CAS

优点

  • 提升用户体验
  • 减少密码管理
  • 统一认证流程
  • 提高安全性

缺点

  • 认证中心单点故障
  • 配置相对复杂
  • 需要额外的安全考虑

什么是跨域?如何实现跨域通讯

跨域是指浏览器的同源策略限制,当前域名的 JavaScript 代码试图访问其他域名下的资源时会受到限制。

同源的定义:

  • 协议相同(http/https)
  • 域名相同
  • 端口相同

跨域解决方案

CORS(跨域资源共享)

  • 服务器设置 Access-Control-Allow-Origin 等响应头
  • 可以配置允许的请求方法、请求头、是否允许携带认证信息等
  • 最常用的跨域解决方案

JSONP

  • 利用 <script> 标签不受同源策略限制的特点,实现跨域请求
  • 只支持 GET 请求
  • 需要服务器配合返回 JavaScript 代码

Proxy代理服务器

  • 开发环境:webpack-dev-server、vite 等的 proxy 配置
  • 生产环境:Nginx 反向代理

WebSocket

  • 建立在 TCP 之上的协议
  • 天然支持跨域
  • 适合需要实时通信的场景

postMessage

  • HTML5 标准中的 API
  • 用于不同窗口间的跨域通信
  • 可以在父子页面(iframe)或者多窗口间通信

最佳实践:

  • 优先使用 CORS,配置得当的情况下最安全
  • 需要兼容旧浏览器时可以考虑 JSONP
  • 开发环境优先使用代理服务器
  • 特殊场景(如页面通信)可以考虑 postMessage
  • 需要实时通信时使用 WebSocket

HTTP 请求跨域时为何要发送 options 请求

OPTIONS 请求是 CORS 预检请求(Preflight Request),用于检查实际请求是否可以安全地发送。

触发条件:

  • 使用非简单请求方法:除 GET、POST、HEAD 之外的方法
  • 使用非简单请求头:除 Accept、Accept-Language、Content-Language、Content-Type 之外的请求头
  • Content-Type 不是以下之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

工作流程

浏览器发送 OPTIONS 预检请求,包含:

  • Origin:请求来源
  • Access-Control-Request-Method:实际请求使用的方法
  • Access-Control-Request-Headers:实际请求使用的请求头

服务器响应预检请求,返回:

  • Access-Control-Allow-Origin:允许的源
  • Access-Control-Allow-Methods:允许的方法
  • Access-Control-Allow-Headers:允许的请求头
  • Access-Control-Max-Age:预检请求的缓存时间

如果预检通过,浏览器才会发送实际请求

优化建议:

  • 尽可能使用简单请求,避免触发预检
  • 合理设置 Access-Control-Max-Age 缓存预检结果
  • 服务端正确配置 CORS 响应头

OPTIONS 请求通常不会携带 Cookie。它是一个预检请求,用于检查实际请求是否可以安全地发送。浏览器在发送 OPTIONS 请求时,不会自动附带 Cookie 和 Authorization 等认证信息,除非明确设置了 credentials 选项。

如果需要在 OPTIONS 请求中携带 Cookie,可以在请求中设置 credentials: 'include',但通常不推荐这样做,因为 OPTIONS 请求的目的就是检查跨域请求的安全性,而不是进行身份验证。

简述浏览器的缓存策略

浏览器缓存策略主要分为两种:强缓存和协商缓存。

强缓存

  • 不需要向服务器发送请求,直接使用本地缓存
  • 通过 HTTP 响应头控制:
    • Cache-Control:
      • max-age:缓存有效时间(秒)
      • no-cache:需要和服务器协商验证
      • no-store:不使用任何缓存
      • private:仅浏览器可缓存
      • public:中间代理/CDN 等也可缓存
      • Expires:过期时间点(已被 Cache-Control 取代)

协商缓存

  • 需要向服务器发送请求验证资源是否有效
  • 如果有效返回 304,使用本地缓存
  • 通过以下响应头实现:
    • Last-Modified/If-Modified-Since:基于文件修改时间
    • ETag/If-None-Match:基于文件内容哈希值

缓存位置(优先级从高到低)

  • Service Worker
  • Memory Cache(内存缓存)
  • Disk Cache(硬盘缓存)
  • Push Cache(HTTP/2)

缓存优先级

Service Worker -> Memory Cache -> Disk Cache -> Push Cache

缓存策略

  • 强缓存优先于协商缓存
  • 协商缓存由服务器决定是否使用缓存
  • 协商缓存失效,返回 200,重新返回资源和缓存标识,再存入浏览器缓存中
  • 协商缓存生效,返回 304,继续使用缓存

最佳实践

  • HTML:使用协商缓存
  • CSS、JS、图片:使用强缓存,文件名带 hash
  • API 请求:根据业务需求设置合适的缓存策略

什么是图片防盗链,如何实现

图片防盗链是指服务器通过 HTTP 协议中的 Referer 字段来判断请求是否来自合法站点,从而防止其他网站直接引用本站图片资源。

实现方式:

服务器端实现

  • 检查 HTTP Referer 字段
  • 判断请求来源是否在白名单中
  • 对非法请求返回 403 或替代图片
nginx
location ~ .*\.(gif|jpg|jpeg|png|bmp)$ {
    valid_referers none blocked server_names *.example.com;
    if ($invalid_referer) {
        return 403;
        # 或者返回替代图片
        # rewrite ^/ /path/to/default.jpg break;
    }
}

其他防盗链方案

  • 给图片添加水印
  • 使用 Token 验证
  • 使用 CDN 提供的防盗链功能
  • 对图片进行加密处理

注意事项

  • Referer 可以被伪造,不能作为唯一判断依据
  • 移动端 APP 可能不发送 Referer
  • 部分浏览器可能禁用 Referer
  • 需要考虑用户体验和 SEO 影响