默认参数

一、参数传递 代码语言:javascript function foo(a, b) { console.log([a, b]); } foo(1, 2); // 输出 [1, 2] 这个例子中,a 和 b 属于函数中的局部变量,只能在函数中访问。调用函数时,传递的数据会根据位置来匹配对应,分别赋值给 a 和 b。 创建函数时,function 函数名 后面括号中设定的参数被称为形参;调用函数时,函数名后面括号中传入的参数被称为实参。上面例子中,a 和 b 是形参,传入的 1 和 2 是实参。 因为形参是已声明的变量,所以不能再用 let 和 const 重复声明。 代码语言:javascript function foo(a, b) { let a = 1; // 报错,a 已声明 const b = 1; // 报错,b 已声明 } JavaScript 中所有函数传递都是按值传递的,不会按引用传递。所谓的值,就是指直接保存在变量上的值,如果把对象作为参数传递,那么这个值就是这个对象的引用,而不是对象本身。这里实际上是一个隐式的赋值过程,所以给函数传递参数时,相当于从一个变量赋值到另一个变量。 原始值: 代码语言:javascript function add(num) { return num + 1; } let count = 5; let result = add(count); // 此处参数传递的过程可以看作是 num = count console.log(count); // 5 console.log(result); // 6 引用值: ...

October 2, 2024

https

阅读本文之前,咱们先来看几道面试题: 什么是HTTPS? HTTPS改进HTTP存在的哪些问题? HTTPS加密原理是什么? 什么是对称加密和非对称加密? HTTPS传输过程? 什么是数字证书?为什么需要数字证书? 为什么需要数字签名? … 如果你能准确无误的回答以上问题,你可以不用继续往下面看了,如果不能,通过阅读这篇文章,我相信你肯定能完全掌握HTTPS。好了废话不多说,我们开始。 什么是 HTTPS 当我们在访问一个地址采用HTTPS协议的Web网站时,浏览器的地址栏内会出现一个带锁的标记,就像这样: 我们想要了解一个东西之前,我们得先知道它是什么,那么HTTPS是什么呢? 可能很多同学都能说道说道:“HTTPS就是能够给我们的请求加密的一个东西”。的确,我们都知道,HTTPS可以加密,但是很多同学的理解仅限于此,无法深层次的理解HTTPS。那么到底什么是HTTPS? HTTPS是在HTTP上建立SSL加密层,并对传输数据进行加密,是HTTP协议的安全版。 说得再简单一点,HTTPS就是 HTTP + SSL: 哦明白了,原来HTTPS就是“披着羊皮的狼”啊。HTTP你肯定是理解的,如果不理解,建议先去阅读HTTP相关知识。 那SSL又是什么呢? 我们都知道,HTTP是应用层的协议,HTTP是直接和TCP通信的,当我们更换为HTTPS的时候,它就演变成了,先和SSL通信、然后再由SSL和TCP通信了。知道了这一流程,我们思考一下,加密过程是在哪个过程进行的? 结果很显然,加密过程就是在HTTP->SSL这一阶段实现的,所以SSL简单来说,就是实现HTTP的加密过程: 对称加密和非对称加密、散列函数这些又是啥啊?没事后面会讲,这些概念你先记住咯。 HTTPS 有什么用 在讲明HTTPS的作用之前,我们先来看看HTTP有哪些弊端: 和服务器通信时,直接采用明文传输,那么明文内容有可能被挟持监听和篡改 由于HTTP本身不具备加密的功能,所以无法做到对通信内容进行加密。也就是说,我们传输的方式,都是直接以明文的形式进行传输,这些明文数据会经过中间代理服务器、路由器、wifi热点、通信服务运营商等多个物理节点,相当于所有通信的数据都在网络中裸奔,想想都刺激。 那么显而易见,明文传输有什么缺陷呢?明文传输可能会导致数据泄露、数据篡改、流量劫持、钓鱼攻击等一系列危险。假设有这么一个场景,某一天,你的另一个女朋友过生日,于是你用浏览器登录了你的邮箱,想给她发送一封生日祝福的邮件。假如这个邮箱网站使用的是HTTP协议,当你点击发送的时候,你的“祝福内容”(注意:是明文),被某个黑客拦截到,然后将这份“祝福内容”直接转发到你的“现任女朋友”,那后果简直不堪设想。 和服务器通信时,无法验证身份 使用HTTP发起请求时,服务器不会验证请求方的身份,响应请求时,请求方也不会验证服务方的身份。说简单点就是,任何人都可以发起请求,同时,服务器只要接收到请求,不管对方是谁都会返回一个响应。所以任何人都可以伪造虚假服务器欺骗用户,实现“钓鱼欺诈”,用户无法察觉,这也是为啥以前我们的qq号老是被盗的原因。 了解到HTTP这些缺陷之后,我们就自然知道了HTTPS到底有什么用: 保证数据的安全性(加密我们的明文数据) 保证数据的完整性 身份认证 HTTPS如何加密(SSL过程) 通过上面的内容,我们知道了HTTPS能够对数据进行加密,那么它具体是如何加密的呢? 这里我们需要先了解两种加密方式: 对称加密 非对称加密 别觉得它们会有多么难理解,心中坚信,一切计算机网络的知识都是纸老虎。 什么是对称加密 那么什么是对称加密呢? 简单说就是有一个密钥,它可以加密数据,也可以对加密后的数据进行解密。试想有这样一个场景:两个港口需要运送一批货物,发货方发货时,将货物装进集装箱并用一把锁将集装箱锁起来,收货方收到货物时,需要用同样的钥匙(不一定是同一把)将集装箱打开,从而取出货物。 所以简单来说,对称加密就是通信双方都有一把同样的钥匙,用于打开同一个集装箱(解密),从而获取数据的一种方式: HTTPS用对称加密可行吗 如果通信双方(浏览器和服务器)都各自拥有同样的私钥,在发送方发送数据之前,将数据锁(加密)起来,然后接收方再用私钥解锁(解密),这样就能完美的保证通信的安全。但是关键的问题就在于,在通信之前,服务器或者浏览器如何同时拥有一把同样的私钥呢?我们来想想办法: 1、服务器给浏览器传输私钥 当浏览器发起请求到服务器时,服务器生成一个私钥,然后传输给浏览器,浏览器拿到之后,他们正式通信就开始用这一个私钥进行加密通信,不就行了?那么问题又来了,假设在传输私钥本身的过程中,被中间人挟持了怎么办?中间人拿到私钥之后,就可以解密通信双方的加密内容了,所以这样做肯定是不可行的。 2、在浏览器里面预留服务器提供的私钥。如果我们浏览器一开始就预留了目标网站的私钥,那这样通信的时候,就只有天知地知你知我知了,这不就行了?但是问题的关键是,世界上的网站千千万,浏览器要预留全部HTTPS协议网站的私钥,这显然不可能啊。 很显然,以上两种假设,都不能实现我们想要的加密效果,所以对称加密暂时被我们 pass. 什么是非对称加密 既然对称加密不行,那么我们就需要考虑非对称加密了,那非对称加密又是什么呢? 我们还是来看看还是刚刚上面👆那个运送货物的例子: 两个港口需要运送一批货物,发货方发货时,将货物装进集装箱并用一把锁(我们将其称为公钥)将集装箱锁起来,收货方收到货物时,需要用另外一把钥匙(我们将其称为私钥)将集装箱打开,从而取出货物。 注意这里的关键是:当通信的一方使用公钥时,另外一方只能使用私钥,反之亦然。 简单的来说就是有两把密钥,一把叫做公钥、一把叫私钥。用公钥加密的内容必须用私钥才能解开,同理,私钥加密的内容只有公钥能解开。公钥对于私钥来说是非对称的,所以我们把这种加密方式称为非对称加密: HTTPS用非对称加密可行吗 我们利用非对称加密来模拟一下浏览器和服务器通信的过程。 浏览器向服务器发起请求,服务器收到请求之后,将公钥传输给浏览器,然后在接下来的通信中,浏览器要向服务器发送数据时,先用公钥将数据加密,然后发送给服务器,服务器收到之后,再用对应的私钥进行解密,这样就保证了浏览器->服务器这条路的数据安全。因为浏览器发送给服务器的数据,只有服务器有私钥能够解密它。那么反过来,服务器->浏览器这条路的通信是否安全呢? 捋一捋刚刚的过程,我们就会发现,一开始我们的服务器将公钥传输给浏览器这一步骤,显然是在明文形式下进行传输的。假设这一过程,我们的公钥被中间人挟持了,想想会发生什么情况?显然有了这个公钥,中间人就能解密由服务器利用私钥加密的数据了,虽然他不能解密浏览器端的数据,但是此时他可以伪造请求,服务器收到请求之后,利用私钥解密请求数据,之后响应请求,并用私钥对响应数据加密,接着返回给请求方,由于此时这个中间人是有对应的公钥的,所以他就能直接解密服务器返回的数据。 ...

October 2, 2024

模版字符串

未见过的函数用法: function fun(strings,params1){ console.log(strings); console.log(params1) } fun`params1 = ${333}` // 输出分别为 // ['params1 = ', ''] // 333 不知道各位在学习或开发中有没有遇到过这样的函数调用方式呢?秉承着我没遇到的东西就要发文章来分享分享的原则,经过我查阅资料并加以学习,就让本文来带大家了解一下JS中的标签函数吧。 模板字符串 标签函数的主要作用就是处理模板字符串,所以在了解标签函数之前先了解一下模板字符串(模板字面量)吧。 基本用法 模板字符串是ES6新增的使用模板字面量定义字符串的能力,用反引号```````` 进行分隔。与使用''或""的定义的字符串字面量不同是模板字面量保留换行字符,可以跨行定义字符串。 例如: let str1 = 'xxhh\n2233' let str2 = `xxhh 2233` console.log(str1 === str2) // 结果为true 要注意的是模板字符串中的所有字符都会包含在字符串中,特别在使用缩进的时候,缩进的空格都会包含在字符串中。 let str = ` <div> <h1>xxhh</h1> </div> ` console.log(str.length) // 结果为44,包含了缩进所产出的所有空格 字符串插值 在没有模板字符串时,我们通常会使用+加法运算符来进行字符串的拼接,但有了模板字符串后我们并可通过插值占位符${}来将各字面量、变量或表达式结果来进行拼接,这样可以更容易地创建复杂和动态的字符串,同时保持代码的可读性和简洁性。这是模板字符串最常用的一个特性。 let name = 'xxhh'; let str1 = "name:"+name; let str2 = `name:${name}`; console.log(str1,str2) // name:xxhh name:xxhh console.log(str1 === str2) // true 要注意的是使用字符串插值的所有插入的值都会使用toString()强制转型为字符串,而且任何JavaScript 表达式都可以用于插值。 ...

October 2, 2024

CSRF攻击

CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求,利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。 一个典型的CSRF攻击有着如下的流程: 受害者登录a.com,并保留了登录凭证(Cookie)。 攻击者引诱受害者访问了b.com。 b.com 向 a.com 发送请求。 a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。 a.com以受害者的名义执行了这个请求。 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。 CSRF的特点 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用” 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。 如何进行预防 CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。 防止csrf常用方案如下: 阻止不明外域的访问 同源检测 Samesite Cookie 提交时要求附加本域才能获取的信息 CSRF Token 双重Cookie验证 同源检测 Cookie的同源和浏览器的同源策略有所区别: 浏览器同源策略:协议、域名和端口都相同即同源; Cookie同源策略:域名相同即同源; 在HTTP协议中,每个异步请求都会携带两个header,用来标记来源域名: Origin Header Referer Header 这两个Header在浏览器发起请求时,大多数情况会自动带上,并且不能由前端修改,服务器接收到后可以根据这两个Header确定来源的域名; 综上所述: 同源验证是一个相对简单的防范方法,能够防范绝大多数的CSRF攻击。但这并不是万无一失的,对于安全性要求较高,或者有较多用户输入内容的网站,我们就要对关键的接口做额外的防护措施。 Samesite Cookie属性 在Chrome 51版本后,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击。 Cookie的Samesite属性用来限制第三方Cookie, 从而减少安全风险,它有三个值: Set-Cookie: SameSite = Strict; Set-Cookie: SameSite = Lax; Set-Cookie: SameSite = None; Strict: 最为严格,完全禁止第三方Cookie, 跨站点时,任何情况都不发送Cookie; Lax: 限制稍微宽松,大多数情况下时不发送第三方Cookie的,除了a链接、预加载请求和GET表单; None: 关闭SameSite属性,但必须同时设置Secure属性, ...

October 2, 2024

XSS防御

一、简述 跨站脚本(Cross-site scripting,简称为:CSS, 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,跨站脚本攻击缩写为XSS)是一种网站应用程序的安全漏洞攻击。 XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、 LiveScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。 二、XSS类型 最常见的几种分类:反射型(非持久型)XSS、存储型(持久型)XSS、DOM型XSS、通用型XSS、突变型XSS。 反射型XSS 反射型XSS只是简单的把用户输入的数据从服务器反射给用户浏览器,要利用这个漏洞,攻击者必须以某种方式诱导用户访问一个精心设计的URL(恶意链接),才能实施攻击。 举例来说,当一个网站的代码中包含类似下面的语句: <?php echo "<p>hello,$_GET['user']</p>"; ?> 如果未做防范XSS,用户名设为<script>alert("Tz")</script>,则会执行预设好的JavaScript代码。 漏洞成因 当用户的输入或者一些用户可控参数未经处理地输出到页面上,就容易产生XSS漏洞。主要场景有以下几种: 将不可信数据插入到HTML标签之间时;// 例如div, p, td; 将不可信数据插入到HTML属性里时;// 例如:<div width=$INPUT></div> 将不可信数据插入到SCRIPT里时;// 例如:<script>var message = ” $INPUT “;</script> 还有插入到Style属性里的情况,同样具有一定的危害性;// 例如<span style=” property : $INPUT ”></span> 将不可信数据插入到HTML URL里时,// 例如:<a href=”[http://www.abcd.com?param=](http://www.ccc.com/?param=) $INPUT ”></a> 使用富文本时,没有使用XSS规则引擎进行编码过滤。 对于以上的几个场景,若服务端或者前端没有做好防范措施,就会出现漏洞隐患。 攻击流程 反射型XSS通常出现在搜索等功能中,需要被攻击者点击对应的链接才能触发,且受到XSS Auditor(chrome内置的XSS保护)、NoScript等防御手段的影响较大,所以它的危害性较存储型要小。 存储型XSS ​ 存储型(或 HTML 注入型/持久型)XSS 攻击最常发生在由社区内容驱动的网站或 Web 邮件网站,不需要特制的链接来执行。黑客仅仅需要提交 XSS 漏洞利用代码(反射型XSS通常只在url中)到一个网站上其他用户可能访问的地方。这些地区可能是博客评论,用户评论,留言板,聊天室,HTML 电子邮件,wikis,和其他的许多地方。一旦用户访问受感染的页,执行是自动的。 漏洞成因 ​ 存储型XSS漏洞的成因与反射型的根源类似,不同的是恶意代码会被保存在服务器中,导致其它用户(前端)和管理员(前后端)在访问资源时执行了恶意代码,用户访问服务器-跨站链接-返回跨站代码。 攻击流程 DOM型XSS 通过修改页面的DOM节点形成的XSS,称之为DOM Based XSS。 ...

October 2, 2024

Let/Const

Var 在 ES6 出现之前,必须使用 var 声明。但是,前端开发出现的一些问题与使用 var 声明的变量有关。这就是为什么必须要有新的方法来声明变量。首先,让我们在讨论这些问题之前更多地了解 var。 var 的作用域 作用域本质上是指变量/函数可供访问的范围。var可以在全局范围声明或函数/局部范围内声明。 当在最外层函数的外部声明var变量时,作用域是全局的。这意味着在最外层函数的外部用var声明的任何变量都可以在windows中使用。 当在函数中声明var时,作用域是局部的。这意味着它只能在函数内访问。 要进一步了解,请查看下面的示例。 var greeter = 'hey hi'; function newFunction() { var hello = 'hello'; } 这里,greeter是全局范围的,因为它存在于函数外部,而hello是函数范围的。因此,我们无法在函数外部访问变量hello。因此,如果我们这样做: var tester = 'hey hi'; function newFunction() { var hello = 'hello'; } console.log(hello); // error: hello is not defined 我们会收到错误消息,这是由于函数外部没有hello导致的。 var 变量可以重新声明和修改 这意味着我们可以在相同的作用域内执行下面的操作,并且不会出错 var greeter = 'hey hi'; var greeter = 'say Hello instead'; 又比如 var greeter = 'hey hi'; greeter = 'say Hello instead'; var 的变量提升 变量提升是 JavaScript 的一种机制:在执行代码之前,变量和函数声明会移至其作用域的顶部。这意味着如果我们这样做: console.log(greeter); var greeter = 'say hello'; 生面的代码会被解释为: var greeter; console.log(greeter); // greeter is undefined greeter = 'say hello'; 因此,将var声明的变量会被提升到其作用域的顶部,并使用 undefined 值对其进行初始化. ...

October 2, 2024

设计模式

说到设计模式,大家想到的就是六大原则,23种模式。这么多模式,并非都要记住,但作为前端开发,对于前端出现率高的设计模式还是有必要了解并掌握的,浅浅掌握9种模式后,整理了这份文章。 那么,我们先了解六大原则 六大原则: 依赖倒置原则(Dependence Inversion Principle):高层(业务层)不应该直接调用底层(基础层)模块 开闭原则(Open Close Principle):单模块对拓展开放、对修改关闭 单一原则(Single Responsibility Principle):单模块负责的职责必须是单一的 迪米特法则(Law of Demeter):对外暴露接口应该简单 接口隔离原则(Interface Segregation Principle):单个接口(类)都应该按业务隔离开 里氏替换原则(Liskov Substitution Principle):子类可以替换父类 六大原则也可以用六个字替换:高内聚低耦合。 高层不直接依赖底层:依赖倒置原则 内部修改关闭,外部开放扩展:开闭原则 聚合单一功能:单一原则 低知识接口,对外接口简单:迪米特法则 耦合多个接口,不如隔离拆分:接口隔离原则 合并复用,子类可以替换父类:里氏替换原则 我们采用模式编写时,要尽可能遵守这六大原则 23 种设计模式分为“创建型”、“行为型”和“结构型” 前端九种设计模式 一、创建型 创建型从功能上来说就是创建元素,目标是规范元素创建步骤 1.构造器模式:抽象了对象实例的变与不变(变的是属性值,不变的是属性名) // 需求:给公司员工创建线上基本信息 // 单个员工创建,可以直接使用创建 const obj = { name:'张三', age:'20', department:'人力资源部门' } // 可员工的数量过于多的时候,一个个创建不可行,那么就可以使用构造器模式 class Person { constructor(obj){ this.name = obj.name this.age = obj.age this.department = obj.department } } const person1 = new Person(obj) 2. 工厂模式:为创建一组相关或相互依赖的对象提供一个接口,且无须指定它们的具体类 即隐藏创建过程、暴露共同接口。 // 需求:公司员工创建完信息后需要为每一个员工创建一个信息名片 class setPerson { constructor(obj) { this.pesonObj = obj } creatCard() { //创建信息名片 } otherFynction(){ } } class Person { constructor(obj) { return new setPerson(obj) } } const person = new Person() const card = person.creatCard({ name:'张三', age:'20', department:'人力资源部门' }) 3. 单例模式:全局只有一个实例,避免重复创建对象,优化性能 // 需求:判断一款应用的开闭状态,根据不同状态给出不同提示 class applicationStation { constructor() { this.state = 'off' } play() { if (this.state === 'on') { console.log('已打开') return } this.state = 'on' } shutdown() { if (this.state === 'off') { console.log('已关闭') return } this.state = 'off' } } window.applicationStation = new applicationStation() // applicationStation.instance = undefined // applicationStation.getInstance = function() { // return function() { // if (!applicationStation.instance) { // 如果全局没有实例再创建 // applicationStation.instance = new applicationStation() // } // return applicationStation.instance // }() // } // application1和application2拥有同一个applicationStation对象 const application1 = window.applicationStation const application2 = window.applicationStation 二、结构型 结构型从功能上来说就是给元素添加行为的,目标是优化结构的实现方式 ...

October 1, 2024

WebWorker

前言 先来聊聊单线程的Javascript 众所周知,js最初设计是运行在浏览器中的,为了防止多个线程同时操作DOM,带来渲染冲突问题,所以js执行器被设计成单线程。但随着前端技术的发展,js能力远不止如此,当我们遇到需要大量计算的场景时(比如图像处理、视频解码等),js线程往往会被长时间阻塞,甚至造成页面卡顿,影响用户体验。为了解决单线程带来的这一弊端,Web Worker 应运而生。 1. Web Worker 1.1 Web Worker 是什么 Web Worker 是 HTML5 标准的一部分,这一规范定义了一套 API,允许我们在 js 主线程之外开辟新的 Worker 线程,并将一段 js 脚本运行其中,它赋予了开发者利用 js 操作多线程的能力。 因为是独立的线程,Worker 线程与 js 主线程能够同时运行,互不阻塞。所以,在我们有大量运算任务时,可以把运算任务交给 Worker 线程去处理,当 Worker 线程计算完成,再把结果返回给 js 主线程。这样,js 主线程只用专注处理业务逻辑,不用耗费过多时间去处理大量复杂计算,从而减少了阻塞时间,也提高了运行效率,页面流畅度和用户体验自然而然也提高了。 1.2 Web Worker 能干些什么 虽然 Worker 线程是在浏览器环境中被唤起,但是它与当前页面窗口运行在不同的全局上下文中,我们常用的顶层对象 window,以及 parent 对象在 Worker 线程上下文中是不可用的。另外,在 Worker 线程上下文中,操作 DOM 的行为也是不可行的,document对象也不存在。但是,location和navigator对象可以以可读方式访问。除此之外,绝大多数 Window 对象上的方法和属性,都被共享到 Worker 上下文全局对象 WorkerGlobalScope 中。同样,Worker 线程上下文也存在一个顶级对象 self。 详细信息请参考:Functions and classes available to Web Workers 2. Web Worker 使用 2.1 创建 worker 创建 worker 只需要通过 new 调用 Worker() 构造函数即可,它接收两个参数 ...

October 1, 2024

前端存储

什么是前端存储 开门见山。前端存储就是通过前端技术来存储一段信息,然后在同源下的不同页面中都可以获取到已存储信息的一种策略。 前端存储的作用 方便网页的加载,避免了在发送请求收到响应前页面的空白期 可以在非强制性要求实时更新时减少向服务端的请求,加快渲染速度 在网络不佳或无网时仍有离线数据可以查看 有哪些前端存储方案 如图,一共有5种前端存储方案。大致可以分为3类: Cookie WebStorage:LocalStorage、SessionStorage 数据库存储:IndexedDB、WebSQL 先做一个简单对比: 下面我们详细介绍。 Cookie Cookie 的工作流程: Cookie 的构成: 域、路径、失效时间和安全性都是服务器给浏览器的指示,它们不会随着请求发送给服务器,发送给服务器的只有名称与值的键值对。 Cookie 的生命周期: 如果设定了 Cookie 的过期时间,那么 Cookie 会在到期时自动失效 如果没有设定过期时间,那么 Cookie 就是 session 级别的,即浏览器关闭时 Cookie 自动消失 Cookie 的优缺点: 优点: 可以控制过期时间,不会永久有效,有一定的安全保障 可进行扩展,可跨域共享 通过加密与安全传输技术,可以减少 Cookie 被破解的可能性 有较高的兼容性 缺点: 存储大小最多4KB 存储数量根据浏览器或浏览器版本的不同而不同,并且每个域最多20条 请求头上的数据容易被拦截攻击 存储的数据只能是字符串类型 操作 Cookie: // 设置 Cookie // Cookie 值必须是字符串类型,并且不支持分号、逗号以及空格, // 所以有时需要先使用 encodeURIComponent() 进行编码,或者使用 JSON.stringify() 进行序列化 document.cookie = '键1=值1;键2=值2;键n=值n'; // 读取 Cookie // 有时需要使用 decodeURIComponent() 或者 JSON.parse() document.cookie // 修改 Cookie // 如果键不存在,就新增;否则就修改 document.cookie = '已经存储过的键=新值'; // 删除 Cookie document.cookie = '要删除的键=任意值;max-age=0'; WebStorage WebStorage 是 HTML5 新加的,WebStorage(Web 存储) 分为 LocalStorage(本地存储) 和 SessionStorage(会话存储)。 ...

October 1, 2024

跨域

一、什么是跨域? 在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。 什么是同源策略? 同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。 同源策略限制以下几种行为: Cookie、LocalStorage 和 IndexDB 无法读取 DOM和JS对象无法获得 AJAX 请求不能发送 二、常见的跨域场景 URL 说明 是否允许通信 www.domain.com/a.js www.domain.com/b.js www.domain.com/lab/c.js 同一域名,不同文件或路径 允许 www.domain.com:8000/a.js www.domain.com/b.js 同一域名,不同端口 不允许 http://www.domain.com/a.js https://www.domain.com/b.js 同一域名,不同协议 不允许 http://www.domain.com/a.js http://192.168.4.12/b.js 域名和域名对应相同ip 不允许 http://www.domain.com/a.js http://x.domain.com/b.js http://domain.com/c.js 主域相同,子域不同 不允许 http://www.domain1.com/a.js http://www.domain2.com/b.js 不同域名 不允许 三、9种跨域解决方案 1、JSONP跨域 jsonp的原理就是利用<script>标签没有跨域限制,通过<script>标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。 1)原生JS实现: <script> var script = document.createElement('script'); script.type = 'text/javascript'; // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数 script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback'; document.head.appendChild(script); // 回调执行函数 function handleCallback(res) { alert(JSON.stringify(res)); } </script> 服务端返回如下(返回时即执行全局函数): ...

October 1, 2024