Map与Set

每当去学习ES6的时候,我都会不由自主的打开阮一峰老师的《ES6入门》去学习和查找用法,相信大多数同学也都和我一样看过阮老师写的文章。 当然大家也都知道ES6里常用的API就那么些,不多不少,用在项目中也是刚刚好。 不过在每次读到Set和Map数据结构那一章的时候,总是有点不知所措,因为我不明白实现这样的数据结构,目的是什么,意义又是什么呢 Set和Map主要的应用场景在于数组去重和数据存储,幸运的是在读了关于数据结构和算法之类的书籍后,恍然大悟的发现 原来Set是一种叫做集合的数据结构,Map是一种叫做字典的数据结构 那么下面就来了解下这两种数据结构,最后来亲手实现的一个ES6中的Set和Map吧 集合 集合是由一组无序且唯一(即不能重复)的项组成的,可以想象成集合是一个既没有重复元素,也没有顺序概念的数组 ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值 Set 本身是一个构造函数,用来生成 Set 数据结构 这里说的Set其实就是我们所要讲到的集合,先来看下基础用法 const s = new Set(); [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)); for (let i of s) { console.log(i); // 2 3 5 4 } // 去除数组的重复成员 let array = [1,2,1,4,5,3]; [...new Set(array)] // [1, 2, 4, 5, 3] 具体用法如果还有不清楚的,这里我会在后面一一细说。现在还是来看一下以ES6中Set类(数据结构)为基础实现的集合吧 Set实例的属性和方法 Set的属性: size:返回集合所包含元素的数量 Set的方法: 操作方法 add(value):向集合添加一个新的项 delete(value):从集合中移除一个值 has(value):如果值在集合中存在,返回true,否则false clear(): 移除集合里所有的项 遍历方法 keys():返回一个包含集合中所有键的数组 values():返回一个包含集合中所有值的数组 entries:返回一个包含集合中所有键值对的数组(感觉没什么用就不实现了) forEach():用于对集合成员执行某种操作,没有返回值 创建一个集合 function Set(arr = []) { // 可以传入数组 let items = {}; this.size = 0; // 记录集合中成员的数量 } module.exports = Set; 这里用{}对象来表示集合,也是因为对象不允许一个键指向两个不同的属性,保证了集合里的元素都是唯一的 ...

October 2, 2024

Class

Class 的基本语法 简介 类的由来 JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。 function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; var p = new Point(1, 2); 上面这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,很容易让新学习这门语言的程序员感到困惑。 ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。 基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写,就是下面这样。 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } 上面代码定义了一个“类”,可以看到里面有一个constructor()方法,这就是构造方法,而this关键字则代表实例对象。这种新的 Class 写法,本质上与本章开头的 ES5 的构造函数Point是一致的。 Point类除了构造方法,还定义了一个toString()方法。注意,定义toString()方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法与方法之间不需要逗号分隔,加了会报错。 ES6 的类,完全可以看作构造函数的另一种写法。 class Point { // ... } typeof Point // "function" Point === Point.prototype.constructor // true 上面代码表明,类的数据类型就是函数,类本身就指向构造函数。 使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。 class Bar { doStuff() { console.log('stuff'); } } const b = new Bar(); b.doStuff() // "stuff" 构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。 ...

October 2, 2024

Async/Await

async/await用法 其实你要实现一个东西之前,最好是先搞清楚这两样东西 这个东西有什么用? 这个东西是怎么用的? 有什么用? async/await的用处就是:用同步方式,执行异步操作,怎么说呢?举个例子 比如我现在有一个需求:先请求完接口1,再去请求接口2,我们通常会这么做 function request(num) { // 模拟接口请求 return new Promise(resolve => { setTimeout(() => { resolve(num * 2) }, 1000) }) } request(1).then(res1 => { console.log(res1) // 1秒后 输出 2 request(2).then(res2 => { console.log(res2) // 2秒后 输出 4 }) }) 或者我现在又有一个需求:先请求完接口1,再拿接口1返回的数据,去当做接口2的请求参数,那我们也可以这么做 request(5).then(res1 => { console.log(res1) // 1秒后 输出 10 request(res1).then(res2 => { console.log(res2) // 2秒后 输出 20 }) }) 其实这么做是没问题的,但是如果嵌套的多了,不免有点不雅观,这个时候就可以用async/await来解决了 async function fn () { const res1 = await request(5) const res2 = await request(res1) console.log(res2) // 2秒后输出 20 } fn() 是怎么用? 还是用刚刚的例子 ...

October 2, 2024

Generator

聊聊 for of 说起 for of 相信每个写过 JavaScript 的人都用过 for of ,平时我们用它做什么呢?大多数情况应该就是遍历数组了,当然,更多时候,我们也会用 map() 或者 filer() 来遍历一个数组。 但是就像我们标题里面说的,它跟 Generator 能扯上什么关系呢? 首先我们想一个问题,为什么使用 for of 或者 map()/filer() 方法就可以遍历一个数组 (或者类数组对象: Strings , Maps , Sets , arguments ) 呢? 为什么不能用他们来遍历一个对象呢? 你能学到什么 对 for of 更深入的理解 iterator 到底是何方神圣? 数组也是对象,为什么不能用 for of 来遍历对象呢? 如何实现对象的 for of? Generator 又是何方神圣?他有什么用呢? 类数组对象的玄机 在真正揭开谜底之前,站在 for of 的角度想一下,现在让你去遍历一个数组,你需要知道什么信息呢? 对应下标的值 是否遍历结束的标志 带着这样的思考,我们打印一个数组来看看这里面的玄机: const numbersArray = [1, 2, 3]; console.dir(numbersArray); 数组 (或者类数组对象: Strings , Maps , Sets , arguments ) 的原型中都实现了一个方法 Symbol.iterator,问题来了,那么这个 Symbol.iterator 又有什么用呢? 拿出来试一下就知道了: ...

October 2, 2024

点击劫持

一、简介 点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上。 虽然受害者点击的是他所看到的网页,但其实他所点击的是被黑客精心构建的另一个置于原网页上面的透明页面 Clickjacking 是仅此于 XSS 和 CSRF 的前端漏洞,因为需要诱使用户交互,攻击成本高,所以不被重视,但危害不容小觑。 点击劫持的步骤 黑客创建一个网页利用 iframe 包含目标网站; 隐藏目标网站,使用户无法无法察觉到目标网站存在; 构造网页,诱变用户点击特点按钮; 用户在不知情的情况下点击按钮,触发执行恶意网页的命令; 二、劫持类型 2.1 Flash点击劫持 攻击者通过flash构造了点击劫持,在完成一系列复杂的动作后,最终控制了用户的摄像头。 攻击者制作了一个Flash游戏,这个游戏就是让用户去点击“CLICK”按钮,每次点击后这个按钮的位置都会发生变化。在Flash上面隐藏了一个看不见的iframe,游戏中某些点击时是有意义的,有些点击是无效的。 攻击通过诱导用户鼠标点击就能完成较复杂的动作。最终通过这一步步操作,打开了用户的摄像头。 2.2 图片覆盖攻击 点击劫持是一种视觉上的欺骗手段。那么图片覆盖也可以起到类似的作用。简称XSIO(Cross Site Image Overlaying) 原理: 利用的是图片的style,或者能够控制CSS。如果应用没有限制style的position为absolute的话,图片可以覆盖到页面上的任意位置。 <img style="position: absolute; left: 100px; top: 100px"> 用户点击图片,就会链接到其他网站。 图片还可以伪装得像一个正常的链接、按钮;或者在图片中构造一些文字,覆盖在关键的位置,就有可能完全改变页面中想表达的意思。这种情况下,不需要用户点击,也能达到欺骗的目的。 由于img标签在很多系统中是对用户开放的,因此在现实生活中有非常多的站点存在在XSIO攻击的可能。在防御XSIO时,需要检查用户提交的HTML代码中,img标签的style属性是否可能导致浮出。 2.3 拖拽劫持与数据窃取 目前,许多浏览器都开始支持Drag和Drop的API。对于用户来说,拖拽使他们的操作更加简单。浏览器中的拖拽对象可以是一个链接,也可以是一段文字,还可以从一个窗口拖拽到另一个窗口,因此拖拽是_不受同源策略限制_的。 拖拽劫持的思路是诱使用户从隐藏不可见iframe中拖拽出攻击者希望得到的数据,然后放到攻击者能控制的另外一个页面,从而窃取数据。在JavaScript的支持下,这个攻击过程会变得非常隐蔽,因为它突破了传统ClickJacking一些先天的局限,所以这种新型的拖拽劫持能够造成更大的破坏。 2.4 ClickJacking3.0:触屏劫持 智能手机的 触屏劫持 攻击被斯坦福的安全研究者公布,这意味着ClickJacking的攻击方式更进一步,斯坦福安全研究者的将其称为TapJacking。 从手机角度来看,触屏实际上就是一个事件,手机捕捉这些事件,并执行相应的动作。 常见的几个事件: touchstart: 手指触摸屏幕时发生 touchend: 手指离开屏幕时发生 touchmove: 手指滑动时发生 touchcancel: 系统可取消touch事件 将一个不可见的iframe覆盖到当前网页上,就可以劫持用户的触屏操作。 在未来,随着移动设备中浏览器功能的丰富,我们会看到更多的TapJacking 三、防御 3.1 防御ClickJacking 3.1.1 frame busting 通过可以写一段JavaScript代码,以禁止iframe的嵌套。这种方法叫作frame busting。比如 ...

October 2, 2024

Promise

Promise 是在 ES6 出现的新功能,并且是用来优化过去回调函式 callback 的写法。这篇面试详解中会讨论到, promise 是什么、为什么需要有 Promise,以及延伸到 async/await 相关问题。 为什么要使用 Promise? 在探讨 Promise 之前,我们先来看一下为什么需要它的出现。 JavaScript 中有一个重要概念 - 异步 (async),它允许我们在执行耗时任务时,不必等待程式完成,而是继续执行下面的代码,直到任务完成再通知。常用的异步操作有:文件操作、数据库操作、AJAX 以及定时器等。 JavaScript 有两种实现异步的方式: 第一种:回调函式 callback function 在 ES6 promise 出现之前,通常使用回调函式 (callback) 实现异步操作。但使用回调函式 callback 存在一个明显的缺点,当需要执行多个异步操作时,代码会不断往内嵌套,这种情况通常被称为「callback 地狱」(callback hell)。 callback(() => { console.log("Hello!"); callback(() => { console.log("Hello!"); callback(() => { console.log("Hello!"); callback(() => { console.log("Hello!"); }, 200); }, 200); }, 200); }, 200); 而为了解决这种问题,就出现了第二种方法 - promise。 什么是 Promise? 上一段提到 Promise 出现的原因,这一段我们来看那到底 Promise 是什么。 ...

October 2, 2024

文件上传安全

文件上传漏洞简介 原理 攻击者可以上传一个与网站脚本语言相对应的恶意代码动态脚本到服务器上,然后访问这些恶意脚本中包含的恶意代码,从而获得了执行服务器端命令的能力,进一步影响服务器安全。 危害 文件上传漏洞最直接的威胁就是上传任意文件,包括恶意脚本、可执行程序等。 如果Web 服务器所保存上传文件的可写目录具有执行权限,那么就可以直接上传后门文件,导致网站沦陷。 如果攻击者通过其他漏洞进行提权操纵,拿到系统管理权限,那么直接导致服务器沦陷。 同服务器下的其他网站无一幸免,均会被攻击者控制。 利用 对于利用,我们只需要有个文件上传的点,以及我们知道我们所传的文件所在目录并且上传的恶意文件能够被web容器解析执行,便可能存在文件上传漏洞。 实战 说是实战但是因为不能随便入侵别人的机器(有概率获取银手镯一套),这里给大家推荐一个专门用来练习文件上传漏洞的不同利用方法的靶场。 github.com/c0ny1/uploa… 可以看到里面有很多关卡,对于环境的搭建,这里我推荐用phpstudy去进行一键搭建,比较适合入门的萌新,具体搭建方法不是本文的重点,于是我们跳过,接下来给大家带来文件上传漏洞一些常见的绕过方法。 客户端检测绕过 有的客户端会存在客户端校验,校验上传文件的后缀名,当我们传入php木马时可能会因为类型不同被禁止,此时我们要怎么进行上传一句话木马呢,这里给大家提供两个思路,第一个我们可以禁用浏览器的JS脚本,第二种方法便是使用渗透中常用工具burpsuit进行抓包,然后修改文件后缀为php即可绕过,因为他只是做了一个前端的简单验证。 修改MIME 类型 有的服务器端将会对上传文件content-type类型进行检查以此来防范恶意文件的上传,这时我们打开burp suite将php文件上传,因为content-type的类型不是服务器认可的类型,那么我们就可以使用burpsuite进行修改该文件类型,并将该文件进行上传。 常见的content-type对应类型如下: 00截断绕过 运用此漏洞需要满足两个条件: 1.php版本小于5.3.4 2.php的magic_quotes_gpc为OFF状态 0x开头表示16进制,0在十六进制中是00, 0x00就是%00解码成的16进制,具体运用方法如下,假如我们上传一个一句话木马: 攻击者修改了path以后的拼接结果为:uploads/XINO.php%00/20190818.php,移动文件的时候会将文件保存为:uploads/XINO.php,以此我们便可以绕过检测来上传一句话木马。 .htaccess文件攻击 .htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。 简单来说该文件的作用就是根据里面的内容解析为我们想要的类型,这么说可能很难理解,比如我上传一个图片马(JPG文件里插入了一句话木马),因为网站对我们的上传类型做了限制,我们上传不了PHP文件,我们先上传一个JPG的图片马,然后上传 .htaccess文件, 将图片解析为php语言,来达到getshell的目的。具体的文件内的内容为: <FilesMatch "evil.gif"> SetHandler application/x-httpd-php#在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行 AddHandler php5-script .gif #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行 </FilesMatch> 当然不止这一种,还能如下写法: AddHandler php5-script .jpg AddType application/x-httpd-php .jpg Sethandler application/x-httpd-php 文件头检测 当我们上传一些文件时,有些拦截会检测我们文件里的具体内容,如果匹配了正确的文件头则会通过检测,反之则会拦截我们的文件,针对如此我们可以利用在文件前写入适当文件类型的文件头来绕过。常用的文件头如下: JPG:FF D8 FF E0 00 10 4A 46 49 46 GIF :47 49 46 38 39 61 (GIF89a) ...

October 2, 2024

export/import

export,import 是什么 我们知道,JS 模块导入导出,使用 import , export 这两个关键字 export 用于对外输出本模块 import 用于导入模块 也就是说使用 export 导出一个模块之后,其它文件就可以使用 import 导入相应的模块了 下面我们具体看看, import 和 export 到底怎么用?怎么导出模块(比如变量,函数,类,对象等) 1 导出单个变量 //a.js 导出一个变量,语法如下 export var site = "www.helloworld.net" //b.js 中使用import 导入上面的变量 import { site } from "/.a.js" //路径根据你的实际情况填写 console.log(site) //输出: www.helloworld.net 2 导出多个变量 上面的例子是导出单个变量,那么如何导出多个变量呢 //a.js 中定义两个变量,并导出 var siteUrl="www.helloworld.net" var siteName="helloworld开发者社区" //将上面的变量导出 export { siteUrl ,siteName } // b.js 中使用这两个变量 import { siteUrl , siteName } from "/.a.js" //路径根据你的实际情况填写 console.log(siteUrl) //输出: www.helloworld.net console.log(siteName) //输出: helloworld开发者社区 ``` ### 3 导出函数 导出函数和导出变量一样,需要添加`{ }` ````js //a.js 中定义并导出一个函数 function sum(a, b) { return a + b } //将函数sum导出 export { sum } //b.js 中导入函数并使用 import { sum } from "/.a.js" //路径根据你的实际情况填写 console.log( sum(4,6) ) //输出: 10 ``` ### 4 导出对象 js中一切皆对象,所以对象一定是可以导出的,并且有两种写法 #### 4.1 第一种写法 使用 `export default` 关键字导出,如下 ````js //a.js 中,定义对象并导出, 注意,使用export default 这两个关键字导出一个对象 export default { siteUrl:'www.helloworld.net', siteName:'helloworld开发者社区' } //b.js 中导入并使用 import obj from './a.js' //路径根据你的实际情况填写 console.log(obj.siteUrl) //输出:www.helloworld.net console.log(obj.siteName) //输出:helloworld开发者社区 ``` #### 4.2 第二种写法 同样是使用`export default` 关键字,如下 ````js //a.js 中定义对象,并在最后导出 var obj = { siteUrl:'www.helloworld.net', siteName:'helloworld开发者社区' } export default obj //导出对象obj //b.js 中导入并使用 import obj from './a.js' //路径根据你的实际情况填写 console.log(obj.siteUrl) //输出:www.helloworld.net console.log(obj.siteName) //输出:helloworld开发者社区 ``` ### 5 导出类 导出类与上面的导出对象类似,同样是用 `export default` 关键字,同样有两种写法 #### 5.1 第一种写法 ````js //a.js 中定义一个类并直接导出 export default class Person { //类的属性 site = "www.helloworld.net" //类的方法 show(){ console.log(this.site) } } //b.js 中导入并使用 //导入类 import Person from './a.js' //创建类的一个对象person let person = new Person() //调用类的方法 person.show() //输出:www.helloworld.net ``` #### 5.2 第二种写法 ````js //a.js 中定义一个类,最后导出 class Person { //类的属性 site = "www.helloworld.net" //类的方法 show(){ console.log(this.site) } } //导出这个类 export default Person //b.js 中导入并使用 //导入类 import Person from './a.js' //创建类的一个对象person let person = new Person() //调用类的方法 person.show() //输出:www.helloworld.net ``` ### 小结 下面我们简单总结一下 `export`与`export default`的区别 * export与export default均可用于导出常量、函数、文件、模块等 * 可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用 * export default后面不能跟const或let的关键词 * export、import可以有多个,export default仅有一个。 * 通过export方式导出,在导入时要加 { },export default则不需要 * export具名导出xxx ,export default匿名。区别在于导入的时候,export需要一样的名称才能匹配,后者无论取什么名都可以。 * 模块化管理中一个文件就是一个模块,export可以导出多个方法和变量,export default只能导出当前模块,一个js文件中只支持出现一个 对于 `import` ,`export` , `export default` ,他们的用法上面的例子已经很详细的列出了,忘记的时候,可以当作参考看看 最重要的还是要明白为什么要这么写,实在不明白记住就行了。 常见考点 1. export 的基本使用 export 用于导出模块中的内容(如变量、函数、类等),使得其他模块能够导入这些内容。 ...

October 2, 2024

展开运算符

ES6 新增了很多特性,扩展运算符就是其中一个。简单的三个点号,让原本繁琐的代码瞬间变得简洁、优雅。就让我们看看它有哪些常见用法吧。 让函数的 Apply 调用方式成为过去 有时候我们需要通过 Function.prototype.apply 来调用函数,参数就放在一个数组里。 function doStuff (x, y, z) { } var args = [0, 1, 2]; // 调用函数并传参 doStuff.apply(null, args); 现在有了展开运算符,我们可以完全避免使用 apply,只需在调用函数时在数组前加上展开运算符: doStuff(...args); 代码变得更短、更简洁,也不需要一个毫无用处的 null! 合并数组 合并数组有各种方式,但是展开运算符为我们提供了一种新思路: arr1.push(...arr2) // 在数组后面添加 arr2 里的元素 arr1.unshift(...arr2) //在数组前面添加 arr2 里的元素 如果你想合并两个数组,并且想把元素放到数组中的任何位置,你可以这么做: var arr1 = ['two', 'three']; var arr2 = ['one', ...arr1, 'four', 'five']; // ["one", "two", "three", "four", "five"] 代码少了很多,还可以随意控制位置! 拷贝数组 拷贝数组是个常见的任务,过去我们使用 Array.prototype.slice 来完成,但现在我们可以通过展开运算符得到数组的副本: var arr = [1,2,3]; var arr2 = [...arr]; // 等同于 arr.slice() arr2.push(4) 这里要注意,数组里的对象仍然是引用类型的,因此实际上并不是所有内容都被“拷贝”了。 将参数或 NodeList 转成数组 跟拷贝数组类似,我们用 Array.Prototype.slice 将 NodeList和 arguments 对象转成真正的数组,但是现在我们可以使用展开运算符完成这个任务: ...

October 2, 2024

密码存储

我们在开发网站或者APP时,首先要解决的问题,就是如何安全地传输和存储用户的密码。一些大公司的用户数据库泄露事件也时有发生,带来非常大的负面影响。因此,如何安全传输存储用户密码,是每位程序员必备的基础。本文将跟大家一起学习,如何安全传输存储用户的密码。 1. 如何安全地传输用户的密码 要拒绝用户密码在网络上裸奔,我们很容易就想到使用https协议,那先来回顾下https相关知识吧~ 1.1 https 协议 「http的三大风险」 为什么要使用https协议呢?http它不香吗? 因为http是明文信息传输的。如果在茫茫的网络海洋,使用http协议,有以下三大风险: 窃听/嗅探风险:第三方可以截获通信数据。 数据篡改风险:第三方获取到通信数据后,会进行恶意修改。 身份伪造风险:第三方可以冒充他人身份参与通信。 如果传输不重要的信息还好,但是传输用户密码这些敏感信息,那可不得了。所以一般都要使用https协议传输用户密码信息。 「https 原理」 https原理是什么呢?为什么它能解决http的三大风险呢? https = http + SSL/TLS, SSL/TLS 是传输层加密协议,它提供内容加密、身份认证、数据完整性校验,以解决数据传输的安全性问题。 为了加深https原理的理解,我们一起复习一下 一次完整https的请求流程吧~ 客户端发起https请求 服务器必须要有一套数字证书,可以自己制作,也可以向权威机构申请。这套证书其实就是一对公私钥。 服务器将自己的数字证书(含有公钥、证书的颁发机构等)发送给客户端。 客户端收到服务器端的数字证书之后,会对其进行验证,主要验证公钥是否有效,比如颁发机构,过期时间等等。如果不通过,则弹出警告框。如果证书没问题,则生成一个密钥(对称加密算法的密钥,其实是一个随机值),并且用证书的公钥对这个随机值加密。 客户端会发起https中的第二个请求,将加密之后的客户端密钥(随机值)发送给服务器。 服务器接收到客户端发来的密钥之后,会用自己的私钥对其进行非对称解密,解密之后得到客户端密钥,然后用客户端密钥对返回数据进行对称加密,这样数据就变成了密文。 服务器将加密后的密文返回给客户端。 客户端收到服务器发返回的密文,用自己的密钥(客户端密钥)对其进行对称解密,得到服务器返回的数据。 「https一定安全吗?」 https的数据传输过程,数据都是密文的,那么,使用了https协议传输密码信息,一定是安全的吗?其实不然 比如,https 完全就是建立在证书可信的基础上的呢。但是如果遇到中间人伪造证书,一旦客户端通过验证,安全性顿时就没了哦!平时各种钓鱼不可描述的网站,很可能就是黑客在诱导用户安装它们的伪造证书! 通过伪造证书,https也是可能被抓包的哦。 1.2 对称加密算法 既然使用了https协议传输用户密码,还是 「不一定安全」,那么,我们就给用户密码 「加密再传输」 呗~ 加密算法有 「对称加密」 和 「非对称加密」 两大类。用哪种类型的加密算法 「靠谱」 呢? 对称加密:加密和解密使用 「相同密钥」 的加密算法。 常用的对称加密算法主要有以下几种哈: 如果使用对称加密算法,需要考虑 「密钥如何给到对方」 ,如果密钥还是网络传输给对方,传输过程,被中间人拿到的话,也是有风险的哦。 1.3 非对称加密算法 再考虑一下非对称加密算法呢? 「非对称加密:」 非对称加密算法需要两个密钥(公开密钥和私有密钥)。公钥与私钥是成对存在的,如果用公钥对数据进行加密,只有对应的私钥才能解密。 ...

October 2, 2024