前端面试常用知识

HTML

h5新增

一:结构标签(语义化标签)

  1. section。section标签定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。
  2. article。article标签装载显示一个独立的文章内容。还可以嵌套,则内层的artilce对外层的article标签有隶属的关系。例如,一个博客文章,可以用article显示,然后一 些评论可以以article的形式嵌入其中。
  3. aside。标签内容之外与标签内容相关的辅助信息;
  4. header。header标签定义文档的页面组合,通常是一些引导和导航信息。
  5. hgroup。hgroup标签用于对网页或区段的标题元素(h1-h6)进行组合。例如,在一个区段中你有连续的h系列的标签元素,则可以用hgroup将他们括起来。
  6. footer。页尾信息;
  7. nav。nav标签定义显示导航链接。
  8. figure。独立的单元,例如某个有图片与内容的新闻块。
  9. time。time标签定义公历的时间(24 小时制)或日期,时间和时区偏移是可选的。该元素能够以机器可读的方式对日期和时间进行编码,这样, 举例说,用户代理能够把生日提醒或排定的事件添加到用户日程表中,搜索引擎也能够生成更智能的搜索结果。
  10. mark。mark标签定义带有记号的文本。请在需要突出显示文本时使用 标签。
  11. figure。figure标签规定独立的流内容(图像、图表、照片、代码等等)。figure 元素的内容应该与主内容相关,但如果被删除,则不应对文档流产生影响。
  12. figcaption。figcaption 标签定义 figure 元素的标题(caption)。“figcaption” 元素应该被置于 “figure” 元素的第一个或最后一个子元素的位置。
  13. contextmenu。contextmenu 标签添加到系统右键菜单 [貌似这个功能只有firefox支持]

二:表单标签

  1. email。必须输入邮件。
  2. url。必须输入url地址。
  3. number。必须输入数值。
  4. range。必须输入一定范围内的数值。
  5. Date Pickers。日期选择器。
  6. search。搜索常规的文本域。
  7. color。颜色。
  8. datalist规定输入域的选项列表
  9. fieldlist表单分组
  10. legend为fieldlist分组描述
  11. keygen的作用是提供一种验证用户的可靠方式
  12. output用于不同类型的输出

三:媒体标签

  1. video。视频
  2. audio。音频
  3. embed。嵌入内容(包括各种媒体),Midi、Wav、AU、MP3、Flash、AIFF等。
  4. source。source设置两份或多份源文件的音频播放器。浏览器应该选择它所支持的文件(如果有的话)
  5. track。诸如 video 元素之类的媒介规定外部文本轨道。用于规定字幕文件或其他包含文本的文件,当媒介播放时,这些文件是可见的。

浏览器渲染过程

  1. 解析HTML,生成DOM树,解析CSS,生成CSSOM树
  2. 将DOM树与CSSOM树结合,生成渲染树(Render tree)
  3. Layout(回流):根据生成地渲染树,进行回流,得到节点的几何信息
  4. Painting(重绘):根据渲染树以及回流得到的节点,获取绝对像素
  5. Display:将像素发给GPU,展示在页面上

DOM树

Nodeelement类型,Text,Comment,Document

CSS

居中方法

水平居中

行内元素:

text-align: center

块级元素:

margin: 0 auto;
position: absolute;
left: 50%;
transform: translateX(-50%)

(父盒子)

display: flex;
justify-content: center;

或者

display: flex;
align-items: center;
flex-direction: column;

垂直居中

line-height: height;
position: absolute;
top: 50%;
transform: translateY(-50%)

(父盒子)

display: flex;
align-items: center;

使用table默认垂直居中,即默认vertical-align: middle,不能简单使用。

垂直和水平居中

position: absolute;
left:50%;
top: 50%;
transform: translate(-50%,-50%);

(父盒子)

display: flex;
align-items: center;
justify-content: center;

(父级为position: relative)

position: absolute;
left: 50%;
top: 50%;
margin-top: -1/2height;
margin-left: -1/2width;

(父级为position: relative)

position: absolute; 
top: 0; bottom: 0; 
left: 0; right: 0; 
margin: auto;
position: absolute;
left: calc(50% - 元素宽度一半);
top: calc(50% - 元素高度一半);
display: grid; // 设置grid布局方式 
justify-items: center; // 主轴居中 
align-items: center; // 交叉轴居中 

选择器优先级

!important > 行内样式 > #id > .class > tag > * > 继承 > 默认

@import和link

  • @import是CSS的语法规则,只有导入样式表的作用;link是html提供的标签,不仅可以加载css文件还可以定义RSS、rel连接属性等
  • 加载顺序:加载页面时,link引入的CSS被同时加载,@import引入的CSS在页面加载完后加载
  • @import是CSS2.1才有的语法
  • 可以通过JS操作DOM,插入link标签来改变样式
  • link引入的权重大于@import

宽度

  • ele.clientWidth = 宽度 + padding
  • ele.offsetWidth = 宽度 + padding + border
  • ele.scrollTop = 被卷去的上侧距离
  • ele.scrollHeight = 自身实际的高端(不包括边框)

display: none和 visibility: hidden

前者直接从dom中删除,引起重绘和回流;后者只是隐藏,引起重绘。

CSS加载

  • 不会阻塞DOM树的解析
  • 会阻塞DOM树的渲染
  • 会阻塞后面JS语句的执行

响应式布局

百分比布局

通过百分比单位,可以使得浏览器中组件的宽和高随着浏览器的高度的变化而变化

rem布局

REMCSS3新增的单位,并且移动端的支持度很高,Android2.x+,ios5+都支持。rem单位都是相对于根元素html的font-size来决定大小的,根元素的font-size相当于提供了一个基准,当页面的size发生变化时,只需要改变font-size的值,那么以rem为固定单位的元素的大小也会发生响应的变化。 因此,如果通过rem来实现响应式的布局,只需要根据视图容器的大小,动态的改变font-size即可(而em是相对于父元素的)。

视口单位

css3中引入了一个新的单位vw/vh,与视图窗口有关,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vwvh外,还有vminvmax两个相关的单位。

Flex弹性布局,兼容性较差

JAVASCRIPT

基本类型

Number、String、Boolean、Null、undefined、object、symbol

函数定义

  • 函数声明:function(){}
  • 函数表达式:var foo = function(){}
  • 构造函数:var foo = new Function()

javascript标准时间模型

事件捕获,事件处理,事件冒泡

数组和链表

在这里插入图片描述

new一个对象的过程

1.加载类

2.执行new,申请一片内存空间

3.调用构造器,创建一个空白对象

4.子类调用父类构造器

5.构造器执行

B树和B+树

B-树有如下特点:

  1. 所有键值分布在整颗树中(索引值和具体data都在每个节点里);
  2. 任何一个关键字出现且只出现在一个结点中;
  3. 搜索有可能在非叶子结点结束(最好情况O(1)就能找到数据);
  4. 在关键字全集内做一次查找,性能逼近二分查找

m阶的b+树的特征:

  1. 有n棵子树的非叶子结点中含有n个关键字(b树是n-1个),这些关键字不保存数据,只用来索引,所有数据都保存在叶子节点(b树是每个关键字都保存数据)。
  2. 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
  3. 所有的非叶子结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字。
  4. 通常在b+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。
  5. 同一个数字会在不同节点中重复出现,根节点的最大元素就是b+树的最大元素。

b+树优点:

  1. b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;
  2. b+树查询必须查找到叶子节点,b树只要匹配到即可不用管元素位置,因此b+树查找更稳定(并不慢);
  3. 对于范围查找来说,b+树只需遍历叶子节点链表即可,b树却需要重复地中序遍历

ECharts底层实现

轻量级的 javascript 图形库, 纯 js 实现;MVC框架;Zrender是Echarts底层依赖的2D向量绘制库。

原型和原型链

在这里插入图片描述

创建一个函数就会为其创建一个prototype属性,指向这个函数的原型对象,原型对象会自动获得constructor属性,指向prototype属性所在函数。

当一个对象调用某个方法或者属性的时候,先在自身查找,如果找到就调用,如果没有就顺着__proto__到原型对象中查找,如果还没有就继续去原型的原型中查找,一直到null,这样形成一条链叫做原型链。如果还没有找到就返回undefined。

继承

原型链继承

重点:新实例的原型等于父类的实例

缺点:无法向父类构造函数传参,一例实例修改了原型属性,所有实例的原型属性都会修改(共享)

function Father(name){
  this.name = name;
  this.sum = function(){
    alert(this.name)
  }
};
Father.prototype.age = 10;
function Son(){
  this.name = "zc";
}
Son.prototype = new Father();//重点
var son1 = new Son();
console.log(son1.age);//10
console.log(son1 instanceof Father)//true

用构造函数继承

解决了原型链继承的缺点,只能继承父类构造函数的属性,每次都要重新调用

function Son(){
  Father.call(this,"zc");
  this.age = 12;
}
son1 = new Son();
console.log(son1.name);//"zc"
console.log(son1.age);//12
console.log(son1 instanceof Father)//false

组合继承(组合原型链继承和借用构造函数继承)

function Son(name){
  Father.call(this,name);
}
Son.prototype = new Father();
var son1 = new Son("zc2");
console.log(son1.name)//"zc2"
console.log(son1.age)//10

原型式继承

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
let person = {
    name:"dd",
    friends:["dds","sss"]
};
let anotherPerson = object(person);
anotherPerson.name = "Gery";
anotherPerson.friends.push("kk");
let anotherGoodPerson = Object.create(person);
anotherGoodPerson.name = "hh";
anotherGoodPerson.friends.push("mkk");
console.log(person.friends)//"dds,sss,kk,mkk"

寄生式继承

function object(o){
    function F() {}
    F.prototype = o;
    return new F();
}
function createAnother(original){
    var clone = object(original);//通过调用函数创建一个新对象
    clone.sayHi = function () {//以某种方式来增强这个对象
        console.log("Hi");
    };
    return clone; //返回这个对象
}

var person = {
    name:"李白",
    friends:["杜甫","陆游"]
};

var anotherPerson = createAnother(person)
anotherPerson.sayHi();//Hi


寄生式组合继承

function inheritPrototype(subType,superType){
    let propertype = object(superType.propertype);
    propertype.constructor = subType;
    subType.prototype = prototype;
};
function SuperType(name){
    this.name = name;
    this.colors = ["ss","ssm"]
};
SuperType.propertype.sayName = function(){
    console.log(this.name)
}
function SubType(name,age){
    SuperType.call(this,name);
    this.age = age;
}
inheritPrototype(subType,superType);
SubType.propertype.sayAge = function(){
    console.log(this.age)
}

通信

常用浏览器引擎

在这里插入图片描述

HTTP 状态码

  • 1xx:指示信息–表示请求已接收,继续处理。

  • 2xx:成功–表示请求已被成功接收、理解、接受。

  • 3xx:重定向–要完成请求必须进行更进一步的操作。

  • 4xx:客户端错误–请求有语法错误或请求无法实现。

  • 5xx:服务器端错误–服务器未能实现合法的请求。

  • 200 OK:客户端请求成功。

  • 400 Bad Request:客户端请求有语法错误,不能被服务器所理解。

  • 401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。

  • 403 Forbidden:服务器收到请求,但是拒绝提供服务。

  • 404 Not Found:请求资源不存在,举个例子:输入了错误的URL。

  • 500 Internal Server Error:服务器发生不可预期的错误。

  • 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子:HTTP/1.1 200 OK(CRLF)。

浏览器输入URL后

  • 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
  • 建立TCP连接(三次握手);
  • 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
  • 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
  • 释放 TCP连接(四次挥手);
  • 浏览器将该 html 文本并显示内容;

同源策略

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
协议、域名、端口只要有一个不一样,就是不同的源。

跨域通信

  • JSONP:在页面上引入不同域上的js脚本文件不受同源策略限制。因此在js文件载入完毕之后,触发回调,可以将需要的data作为参数传入。 优点:兼容性好(兼容低版本IE) 缺点:JSONP只支持GET请求
  • CORS:根据请求头的Origin值和响应头的Access-Control-Request-HeadersAccess-Control-Request-Method的值进行比对,通过了就可以请求成功,没通过就请求失败
  • postMessage (H5中新增的),window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源
  • node反向代理:如果我们用的是node起的前端服务,那我们可以使用node来直接进行反向代理,引入一个处理代理的插件,然后配置一个target
  • Nginx反向代理:主要就是用了nginx.conf内的proxy_pass http://xxx.xxx.xxx,会把所有请求代理到那个域名
  • WebSocket
  • Hash(window.location.hash + iframe)

Cookie、sessionStorage、localStorage区别

共同点:都是保存在浏览器端,且同源的。

区别:

  • cookie数据始终在同源的http请求中携带,即cookie在浏览器和服务器间来回传递。sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
  • cookie数据不能超过4k(适合保存小数据)。 sessionStorage和localStorage容量较大,
  • 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效。localStorage:始终有效,窗口或浏览器关闭也一直保存,需手动清除;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
  • 作用域不同。 sessionStorage不在不同的浏览器窗口中共享;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。

GET和POST的区别

  • 简单来说:GET产生一个TCP数据包,POST产生两个TCP数据包

  • 严格的说:对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST请求。浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)

  • GET请求的参数是放在请求的URL中,而POST方法是放在请求体中

  • GET请求在URL中传递参数时会有长度限制,而POST无限制(不是绝对的,只是相对来说)

  • GET请求会被浏览器主动缓存,而POST不会

  • GET请求的参数会保存在浏览器中,而POST的参数不会保存在浏览器中

Promise

优点

  1. 链式调用,解决回调地狱的问题
  2. 可以更灵活地使用回调函数

TCP三次握手

第一次握手
客户主动(active open)去connect服务器,并且发送SYN 假设序列号为J,
服务器是被动打开(passive open)

第二次握手
服务器在收到SYN后,它会发送一个SYN以及一个ACK(应答)给客户,
ACK的序列号是 J+1表示是给SYN J的应答,新发送的SYN K 序列号是K

第三次握手
客户在收到新SYN K, ACK J+1 后,也回应ACK K+1 以表示收到了,
然后两边就可以开始数据发送数据了

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

​ 现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

TCP/IP是一系列网络协议的总称

UDP不可靠

CDN是内容分发网络,广泛应用各种缓存服务器

OSI七层协议模型

在这里插入图片描述在这里插入图片描述

进程和线程

进程是资源分配的最小单位,线程是CPU调度的最小单位

线程在进程下行进(单纯的车厢无法运行)

一个进程可以包含多个线程(一辆火车可以有多个车厢)

不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)

同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)

进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)

进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)

进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)

进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-“互斥锁”

进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”

进程间的通信方式

管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享存储SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

PV操作

临界区:我们把并发进程中与共享变量有关的程序段称为临界区。

信号量S:信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。

P操作和V操作

P操作P(S):将信号量S减去1,若结果小于0,则把调用P(S)的进程置成等待信号量S的状态。即为请求资源。

V操作V(S):将信号量S加上1,若结果不大于0,则释放一个等待信号量S的进程。即为释放资源。

断开通信

  1. 对于http1.0协议来说,如果响应头中有content-length头,则以content-length的长度就可以知道body的长度了,客户端在接收body时,就可以依照这个长度来接收数据,接收完后,就表示这个请求完成了。而如果没有content-length头,则客户端会一直接收数据,直到服务端主动断开连接,才表示body接收完了。
  2. 而对于http1.1协议来说,如果响应头中的Transfer-encoding为chunked传输,则表示body是流式输出,body会被分成多个块,每块的开始会标识出当前块的长度,此时,body不需要通过长度来指定。如果是非chunked传输,而且有content-length,则按照content-length来接收数据。否则,如果是非chunked,并且没有content-length,则客户端接收数据,直到服务端主动断开连接。

内存泄漏

1.被遗忘的定时器

2.使用不当的闭包

3.脱离 DOM 的引用

有时,保存 DOM 节点内部数据结构很有用。假如你想快速更新表格的几行内容,把每一行 DOM 存成字典(JSON 键值对)或者数组很有意义。此时,同样的 DOM 元素存在两个引用:一个在 DOM 树中,另一个在字典中。将来你决定删除这些行时,需要把两个引用都清除。

性能优化

1压缩

2重绘而不是回流:

  • 避免使用 table 布局。

  • 尽可能在 DOM 树的最末端改变 class。

  • 避免设置多层内联样式。

  • 将动画效果应用到 position 属性为 absolute 或 fixed 的元素上。

  • 避免使用 CSS 表达式(例如:calc())。

    3图片懒加载

    4减少http请求

前端攻击和防御

XSS(Cross Site Scripting)跨站脚本攻击

(1)原理:页面渲染的数据中包含可运行的脚本

(2)攻击的基本类型:反射型(url参数直接注入)和存储型(存储到DB后读取时注入)

(3)注入点:HTML节点内的内容(text);HTML中DOM元素的属性;Javascript代码;富文本

XSS攻击防御

(1)浏览器自带防御机制,主要应对反射型攻击(HTML内容或属性):http响应头中自动添加x-xss-protection,值为0(关闭),1(打开),默认打开

(2)对特定字符做转义:内容注入替换尖括号( < => < > => > ) 属性注入替换单引号或双引号( " => " ’ => ’ )

(3)CSP(Content Security Policy)内容安全策略:用于指定哪些内容可执行

CSRF(Cross Site Request Forgy)跨站请求伪造

原理:在第三方网站向本网站发起请求(如图)

img

(1)用户在a站前端页面发起登录(身份认证)请求

(2)a站后端确认身份,登录成功,cookie中存在用户的身份认证信息

(3)b站前端页面向a站后端发起请求,带着a站的cookie信息(身份认证信息),请求成功

CSRF攻击防御:

CSRF的发生有几个特点,b站发送的请求带着a站的cookie信息; b站发送请求不经过a站的前端;http请求头中的referer为b站。我们可以从这些特点入手,思考防御的办法

(1)禁止第三方网站携带本网站的cookie信息:设置same-site属性,same-site属性有两个值,Strict(所有的第三方请求都不能携带本网站的cookie)和Lax(链接可以,但是form表单提交和ajax请求不行

(2)本网站前端页面添加验证信息:使用验证码或者添加token验证

验证码:当发起请求时,前端需要输入本网站页面的验证码信息,后端对验证码进行验证,验证码正确才会进行相关操作(存取数据等)

token验证:a站前端将token存在当前页面中(比如表单中的input隐藏域,meta标签或者任何一个dom的属性)和cookie中,当请求a站后端的时候,参数中带上这个token字段,a站后端将参数中的token和cookie中的token做对比, 相同则验证通过,不同则请求不合法

不管是验证码还是token验证,原理都是一样的,在a站前端页面加入验证,当第三方网站请求a站后端时,即使能携带a站cookie,但是因为没有经过a站的前端页面从而拿不到验证信息,也会导致请求失败。

两种防御的方法也有区别,验证码需要用户去填写,从而增加了用户使用网站的复杂度,而token验证在用户无感知的情况下就可以实现,不影响用户体验。我个人理解,验证码验证一般使用在需要提高用户认知的场景,比如,登录多次失败,修改个人信息(用户名,密码,绑定手机号等等),而一些获取商品列表信息,搜索等接口,使用token比较合理。可以看看我们平时使用的这些网站,作参考~

referer验证:禁止来自第三方的请求

Iframe网页嵌套

Vue

全家桶

vue-cli也叫脚手架,官方定义为Vue.js 开发的标准工具!相比scirpt标签引入,脚手架具有如下特点

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

1)嵌套的路由/视图表
2)模块化的、基于组件的路由配置
3)路由参数、查询、通配符
4)基于 Vue.js 过渡系统的视图过渡效果
5)细粒度的导航控制
6)带有自动激活的 CSS class 的链接
7)HTML5 历史模式或 hash 模式,在 IE9 中自动降级
8)自定义的滚动条行为

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
特性
1)从浏览器中创建 XMLHttpRequests
2)从 node.js 创建 http 请求
3)支持 Promise API
4)拦截请求和响应
5)转换请求数据和响应数据
6)取消请求
7)自动转换 JSON 数据
8)客户端支持防御 XSRF

!相比scirpt标签引入,脚手架具有如下特点

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

1)嵌套的路由/视图表
2)模块化的、基于组件的路由配置
3)路由参数、查询、通配符
4)基于 Vue.js 过渡系统的视图过渡效果
5)细粒度的导航控制
6)带有自动激活的 CSS class 的链接
7)HTML5 历史模式或 hash 模式,在 IE9 中自动降级
8)自定义的滚动条行为

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
特性
1)从浏览器中创建 XMLHttpRequests
2)从 node.js 创建 http 请求
3)支持 Promise API
4)拦截请求和响应
5)转换请求数据和响应数据
6)取消请求
7)自动转换 JSON 数据
8)客户端支持防御 XSRF

智力题

25匹马,5个赛道,赛出前三

7次

10个正面朝上,23个硬币,分两堆正面朝上一样

砝码秤盐

140g盐,一天平,7g 、2g砝码各一个,如何只利用这些东西3次把盐分成50g和90g?

第一次: 7g、2g砝码称出9g盐,结果盐分成9g与131g

第二次:将9g盐与7g、2g都作为砝码,结果将盐分为18g与113g (注意:这时盐已经分为三份:9g、18g、113g,还有两个砝码)

第三次:将18g盐与7g砝码发在左托盘,将2g砝码放在右托盘,然后在113g盐中取盐添置右托盘中,可获取23g盐。

这时盐分为9g,18g,23g与90g。

即三次,可以得到90g与(9+18+23)50g。

解法2:

第一步:把140克盐分成两等份,每份70克。
第二步:把天平一边放上2+7克砝码,另一边放盐,这样就得到9克和61克分开的盐。
第三步:将9克盐和2克砝码放在天平一边,另一边放盐,这样就得到11克和50克。于是50和90就分开了

经典的海盗分金问题

5个海盗抢得100枚金币,他们按抽签的顺序依次提方案:首先由1号提出分配方案,然后所有5人表决(包括自己),超过半数同意方案才被通过,否则他将被扔入大海喂鲨鱼,依此类推。

大盗们都有如下的几个性格特点:

1.足智多谋,总是采取最优策略。
2.贪生怕死,尽量保全自己性命。
3.贪得无厌,希望自己得到越多宝石越好
4.心狠手辣,在自己利益最大的情况想希望越多人死越好。
5.疑心多虑,不信任彼此,尽量确保自身利益不寄希望与别人给自己更大利益。

在这种理想的条件下如果你是第一个海盗应该怎么提出方案才能让自己的收获最多的金币呢.

不科学的结论

按照一般的思想,我们肯定认为第一个人是最惨的,因为似乎只要死的人越多,平均每个人能分到的金币就更多,那么第一个人可能是很容易就死了,但是实际上呢,在上面的这些条件下,第一个海盗是最赚的,他能得到的金币是97个!!!

有趣的推理:

我们先来看两个海盗的时候会怎么样,慢慢推理,然后我们就会发现其实很好理解.

两个海盗–毫无悬念

很显然,当只有两个海盗的时候,一号一定会死,因为首先只要第一个海盗死了,剩下的一个便能获得全部的金币,根据贪得无厌的原则,二号也不会投同意票,即使一号选择
(0,100)(即一号获得0个金币,二号获得100个),但是根据心狠手辣的原则,二号还是不会投同意票,所以此时无论如何也不会有半数以上的同意票,此时的一号表示:为什么我这么惨啊!

结果 (0, 100)

三个海盗–无奈的选择

当存在三个海盗的时候,原来的两个海盗时的一号变成了二号,此时二号知道了,如果一号被投死,那么毫无悬念的,他没有任何活路,根据贪生怕死的原则,他会无论如何保全自己,换句话说,他无论如何都会同意此时一号的题意,那么此时聪明的一号知道他们的想法之后就开心的不行了,因为无论自己提什么条件自己都会得到半数以上的投票.那根据贪得无厌的原则,结果显而易见.

结果 (100, 0, 0)

四个海盗–稍稍讨好就可以

四个海盗时,此时的一号明白了此时的二号是讨好不了的.因为自己死了二号就一定能得到全部100枚金币,所以干脆不讨好,给他0枚金币吧.而此时除了自己的票还差两票,那么只要讨好三号和四号获得这两票就好,三号和四号相当容易讨好的,因为一号死了,他们就只能得到空气(三个海盗的结果为(100, 0, 0)),那么给他一块金币就好啦.当然一号不能不给三号四号金币,因为海盗都是心狠手辣的,[如果不管你死不死我都是0块金币,那我干脆要你死算了].

结果 (98, 0, 1, 1)

五个海盗–照本宣科

相同的原理,现在的一号需要2票就能保证存活,首先二号是不考虑了给金币了,不管给多少都反对的,三号给一个金币就行,然后还差一票,只要给四号或五号其中一个两枚金币,另一个不给,就可以.但这里要注意一下,此时的分歧已经产生,后面的推广推理中会用到.

结果: (97, 0, 1, 2, 0)或(97, 0, 1, 0, 2)

到这里我们关于五个海盗分金币的问题就得到了完美的解决,看似最惨的一号海盗得到了最多的获利,令人侧目,可惜人不都是完全理性的,有时甚至愚蠢之极,但这或许就是社会令人难以着迷也最令人害怕的地方的地方.


更多的推广和规律

五个海盗的故事结束了,现在来了六个海盗,

我们继续可以按照之前的思路分析现在的情况,一号需要3票,二号不能讨好,三号给一枚,四号五号六号呢,这就出现的不是很好理解的情况,我先说明最后的结果是:

(97, 0, 1, 0, 1, 1)

为什么呢,我们可以从上面的推理发现我们其实一直没用到5.疑心多虑的原则,而现在就用到了,因为在五个海盗的时候有两种分法,四号和五号都可能分到2枚金币,也都可能分到0枚,他们不敢保证自己在这个人死后下一个人提方案时会给自己2枚还是0枚,那现在只要一号给他们一枚金币,他们就一定会投同意票
(不信任彼此,尽量确保自身利益不寄希望与别人给自己更大利益).

所以这种分法是对一号收益最多的,否则他还要要花两枚金币去收买四号,一枚金币收买五六号中的一个 ((96, 0, 1, 2, 0, 1)或(96, 0, 1, 2, 1, 0)),这样不是最优的.

同样的思路推广下去我们会发现这样的规律:

当 n为偶数时只要给二号到n号0,1,0,1…0,1,0,1,1
当 n 为奇数时给1,x,1,x…x,x.(任意一个x是二其余都是0)

上述情况的答案都是m-n/2

这就是海盗分金币的一般解了.

用绳子计时 15 分钟

给定两条绳子,每条绳子烧完正好一个小时,并且绳子是不均匀的。问要怎么准确测量 15 分钟。

点燃第一条绳子 R1 两头的同时,点燃第二条绳子 R2 的一头;

当 R1 烧完,正好过去 30 分钟,而 R2 还可以再烧 30 分钟;

点燃 R2 的另一头,15 分钟后,R2 将全部烧完。

药丸称重

有 20 瓶药丸,其中 19 瓶药丸质量相同为 1 克,剩下一瓶药丸质量为 1.1 克。瓶子中有无数个药丸。要求用一次天平找出药丸质量 1.1 克的药瓶。

可以从药丸的数量上来制造差异:从第 i 瓶药丸中取出 i 个药丸,然后一起称重。可以知道,如果第 i 瓶药丸重 1.1 克/粒,那么称重结果就会比正常情况下重 0.1 * i 克。

得到 4 升的水

有两个杯子,容量分别为 5 升和 3 升,水的供应不断。问怎么用这两个杯子得到 4 升的水。

5L里倒满水往3升里倒,倒满了,5L杯还剩2L,把三L里的水倒了,2L水放在3L容器中,5L接满3L容器里倒

扔鸡蛋

一栋楼有 100 层,在第 N 层或者更高扔鸡蛋会破,而第 N 层往下则不会。给 2 个鸡蛋,求 N,要求最差的情况下扔鸡蛋的次数最少。

可以将楼层划分成多个区间,第一个鸡蛋 E1 用来确定 N 属于哪个区间,第二个鸡蛋 E2 按顺序遍历该区间找到 N。那么问题就转换为怎么划分区间满足最坏情况下扔鸡蛋次数最少。

E1 需要从第一个区间开始遍历到最后一个区间。如果按等大小的方式划分区间,即 E2 的遍历次数固定。那么最坏的情况是 N 在最后一个区间,此时 E1 遍历的次数最多。为了使最坏情况下 E1 和 E2 总共遍历的次数比较少,那么后面的区间大小要比前面的区间更小。具体来说,E1 每多遍历一次,E2 要少遍历一次,才使得 N 无论在哪个区间,总共遍历的次数一样。设第一个区间大小为 X,那么第二个区间的大小为 X-1,以此类推。那么 X + (X-1) + (X-2) + … + 1 = 100,得到 X (X + 1) / 2 = 100 ,即 X = 14。

一硬币,一面向上概率0.7,一面0.3,如何公平?

抛两次,正反A胜,反正B胜。

两个人轮流抛硬币,先抛到正面的赢,问先抛的人赢的概率

2/3

每一轮抛硬币,A先抛赢得概率是1/2,B后抛赢得概率是(1/2)*(1/2)= 1/4。那么每一轮A赢得概率都是B赢得概率的2倍,总概率为1,所以A赢的概率是2/3。

1000个苹果分在10个篮子里,问如何分配使得想取任意个苹果的时候都能整篮提走?

2的10次方,考查二进制

1000个苹果分10个篮子,的方法,应该是:按篮子次序分别放:1、2、4、8、16、32、64、128、256、512。(第10个篮子照理应该放512个苹果,但这里只能放489个苹果,因为照前面10个数字加起来的和是1023,现在只有1000个苹果,还缺23个所以最后一个篮子只能放489个)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值