OSI七层模型
应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
TCP/IP五层模型
应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 传输层:TCP,UDP 网络层:IP,ICMP,RIP,OSPF,BGP,IGMP 数据链路层:SLIP,CSLIP,PPP,ARP,RARP,MTU 物理层
参考链接:HTTP/2 相比 1.0 有哪些重大改进?
TCP:传输控制协议 UDP:用户数据报协议
参考链接:HTML5 WebSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每 1 秒),由浏览器对服务器发出 HTTP 请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而 HTTP 请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-178Fgn1E-1618798622752)(…/images/websocket.png)]
应用场景:实现即时通讯:如股票交易行情分析、聊天室、在线游戏等,替代轮询和长轮询
我对浏览器的同源政策的理解是,一个域下的 js 脚本在未经允许的情况下,不能够访问另一个域的内容。这里的同源的指的是两个 域的协议、域名、端口号必须相同,否则则不属于同一个域。 同源政策主要限制了三个方面 第一个是当前域下的 js 脚本不能够访问其他域下的 cookie、localStorage 和 indexDB。 第二个是当前域下的 js 脚本不能够操作访问其他域下的 DOM。 第三个是当前域下 ajax 无法发送跨域请求。 同源政策的目的主要是为了保证用户的信息安全,它只是对 js 脚本的一种限制,并不是对浏览器的限制,对于一般的 img、或者 script 脚本请求都不会有跨域的限制,这是因为这些操作都不会通过响应结果来进行可能出现安全问题的操作。
两者本质上都是 TCP 链接
参考链接:在浏览器输入 URL 回车之后发生了什么(超详细版)
1.存储位置不同:
cookie 数据存放在客户的浏览器上
session 数据放在服务器上。
2.存储容量不同:
单个 cookie 保存的数据不能超过 4K,一个站点最多保存 20 个 cookie。
对于 session 来说并没有上限,但出于对服务器端的性能考虑,session 内不要存放过多的东西,并且设置 session 删除机制。
3.存储方式不同:
cookie 中只能保管 ASCII 字符串,并需要通过编码方式存储为 Unicode 字符或者二进制数据。
session 中能够存储任何类型的数据,包括且不限于 string,integer,list,map 等。
4.隐私策略不同
cookie 对客户端是可见的,别有用心的人可以分析存放在本地的 cookie 并进行 cookie 欺骗,所以它是不安全的。
session 存储在服务器上,不存在敏感信息泄漏的风险。
5.有效期不同
cookie 保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie 是很好的选择。
session 是保管在服务器端的,每个用户都会产生一个 session。假如并发访问的用户十分多,会产生十分多的 session,耗费大量的内存。
不行! 只能向当前域或者更高级域设置cookie
例如 client.com 不能向 a.client.com 设置cookie, 而 a.client.com 可以向 client.com 设置cookie
读取cookie情况同上
无论是客户端还是服务端, 都只能向自己的域或者更高级域设置cookie,例如 client.com 不能向 server.com 设置cookie, 同样 server.com 也不能向 client.com 设置cookie
服务端可以设置
httpOnly: true
, 带有该属性的cookie客户端无法读取客户端只会带上与请求同域的cookie, 例如 client.com/index.html 会带上 client.com 的cookie,server.com/app.js 会带上 server.com 的cookie, 并且也会带上httpOnly的cookie
fetch在默认情况下, 不管是同域还是跨域ajax请求都不会带上cookie, 只有当设置了 credentials 时才会带上该ajax请求所在域的cookie, 服务端需要设置响应头
Access-Control-Allow-Credentials: true
, 否则浏览器会因为安全限制而报错, 拿不到响应axios和jQuery在同域ajax请求时会带上cookie, 跨域请求不会, 跨域请求需要设置
withCredentials
和服务端响应头Access-Control-Allow-Credentials
fetch 设置 credentials 使fetch带上cookie
fetch(url, { credentials: "include", // include, same-origin, omit })
axios 设置 withCredentials 使axios带上cookie
axios.get('http://server.com', {withCredentials: true})
jQuery 设置 withCredentials
$.ajax({ method: 'get', url: 'http://server.com', xhrFields: { withCredentials: true } })
XSS攻击形式:
主要是通过html标签注入,篡改网页,插入恶意的脚本,前端可能没有经过严格的校验直接就进到数据库,数据库又通过前端程序又回显到浏览器
例如一个留言板: 如果内容是 hello!<script type="type/javascript src="恶意网址"></script> 这样会通过前端代码来执行js脚本,如果这个恶意网址通过cookie获得了用户的私密信息,那么用户的信息就被盗了
攻击的目的:
攻击者可通过这种方式拿到用户的一些信息,例如cookie 获取敏感信息,甚至自己建网站,做一些非法的操作等;或者,拿到数据后以用户的身份进行勒索,发一下不好的信息等。
攻击防御
方法1:cookie中设置 HttpOnly 属性
方法2:首先前端要对用户输入的信息进行过滤,可以用正则,通过替换标签的方式进行转码或解码,例如<> 空格 & ‘’ ""等替换成html编码
htmlEncodeByRegExp:function (str){ var s = ""; if(str.length == 0) return ""; s = str.replace(/&/g,"&"); s = s.replace(/</g,"<"); s = s.replace(/>/g,">"); s = s.replace(/ /g," "); s = s.replace(/\'/g,"'"); s = s.replace(/\"/g,"""); return s; }
CSRF攻击形式:
CSRF也是一种网络攻击方式,比起xss攻击,是另外一种更具危险性的攻击方式,xss是站点用户进行攻击,而csrf是通过伪装成站点用户进行攻击,而且防范的资源也少,难以防范
csrf攻击形式:攻击者盗用用户的身份信息,并以用户的名义进行发送恶意的请求等,例如发邮件,盗取账号等非法手段
例如:你登录网站,并在本地种下了cookie 如果在没退出该网站的时候 不小心访问了恶意网站,而且这个网站需要你发一些请求等 此时,你是携带cookie进行访问的,那么你的种在cookie里的信息就会被恶意网站捕捉到,那么你的信息就被盗用,导致一些不法分子做一些事情
攻击防御:
验证HTTP Referer字段
在HTTP头中有Referer字段,他记录该HTTP请求的来源地址,如果跳转的网站与来源地址相符,那就是合法的,如果不符则可能是csrf攻击,拒绝该请求
在请求地址中添加token并验证
这种的话在请求的时候加一个token,值可以是随机产生的一段数字, token是存入数据库之后,后台返给客户端的,如果客户端再次登录的时候, 后台发现token没有,或者通过查询数据库不正确,那么就拒绝该请求 如果想防止一个账号避免在不同的机器上登录,那么我们就可以通过token来判断, 如果a机器登录后,我们就将用户的token从数据库清除,从新生成, 那么另外一台b机器在执行操作的时候,token就失效了,只能重新登录,这样就可以防止两台机器登同一账号
在HTTP头中自定义属性并验证
如果说通过每次请求的时候都得加token那么各个接口都得加很麻烦, 那么我们通过http的请求头来设置token 例如: $.ajax({ url: '/v1/api', dataType: 'json', data: param, type:'post', headers: {'Accept':'application/json','Authorization':tokenValue} success:function(res){ console.log(res) } })
参考链接:HTTP 强缓存和协商缓存
浏览器缓存分为:强缓存和协商缓存
在浏览器第一次发起请求时,本地无缓存,向 web 服务器发送请求,服务器起端响应请求,浏览器端缓存。在第一次请求时,服务器会将页面最后修改时间通过 Last-Modified 标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个 Etag,并发送给客户端。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wfsqA0s5-1618798622772)(…/images/浏览器缓存.png)]
根据上图,浏览器在第一次请求发生后,再次发送请求时:
强缓存是利用 http 头中的 Expires 和 Cache-Control 两个字段来控制的,用来表示资源的缓存时间。强缓存中,普通刷新会忽略它,但不会清除它,需要强制刷新。浏览器强制刷新,请求会带上Cache-Control:no-cache
和 Pragma:no-cache
Expires 的值是一个绝对时间的 GMT 格式的时间字符串。比如 Expires 值是:expires:Fri, 14 Apr 2017 10:47:02 GMT
。这个时间代表这这个资源的失效时间,只要发送请求时间是在 Expires 之前,那么本地缓存始终有效,则在缓存中读取数据。
缺点:
由于失效的时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,误差很大,就会导致缓存混乱。
Cache-Control 主要是利用该字段的 max-age
值来进行判断,它是一个相对时间,例如Cache-Control:max-age=3600
,代表着资源的有效期是 3600 秒。
cache-control 除了该字段外,还有下面几个比较常用的设置值:
Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。如:
cache-control:max-age=691200 expires:Fri, 15 May 2020 10:47:02 GMT
那么表示资源可以被缓存的最长时间为 691200 秒。
协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问。
Etag/If-None-Match
返回的是一个校验码。Etag
可以保证每一个资源是唯一的,资源变化都会导致Etag
变化。服务器根据浏览器发送的If-None-Match
值来判断是否命中缓存。
与Last-Modified
不一样的是,当服务器返回 304 (Not Modified) 的响应时,由于Etag
重新生成过,response header 中还会把这个Etag
返回,即使这个Etag
跟之前的没有变化。
浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-Modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。
两个都可以确定缓存资源的是否可用,有什么区别呢?
Etag
的出现主要是为了解决几个 Last-Modified
比较难解决的问题:
If-Modified-Since
能检查到的力度是秒级的,这种修改无法判断;Last-Modified
与 ETag
是可以一起使用的,服务器会优先验证ETag
,一致的情况下,才会继续比对 Last-Modified
,最后才决定是否返回 304。
官网定义: 进程是系统进行资源分配和调度的基本单位 线程是操作系统能够进行运算调度的最小单位 简单理解: 进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。 线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。 借助阮一峰老师的解释 1.计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。 2.假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。 3.进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。 4.一个车间里,可以有很多工人。他们协同完成一个任务。 5.线程就好比车间里的工人。一个进程可以包括多个线程。 6.车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。 7.可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。 这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。 8.一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。 这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。 9.还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。 10.这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。 这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。 操作系统的设计,因此可以归结为三点: (1)以多进程形式,允许多个任务同时运行; (2)以多线程形式,允许单个任务分成不同的部分运行; (3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。