深厚内功才是硬道理

HTTP缓存、cookies、访问控制、发展、消息

2019-04-05  本文已影响0人  Aniwer

3月25日 周一 HTTP缓存

·加速资源

更好地利用缓存资源,可以提高网站的性能和响应速度。为了优化缓存,过期时间设置得尽量长是一种很好的策略。对于定期或者频繁更新的资源,这么做是比较稳妥的,但对于那些长期不更新的资源会有点问题。这些固定的资源在一定时间内受益于这种长期保存的缓存策略,但一要更新就会很困难,特指网页上引入的一些js/css文件,当它们变动时需要尽快更新线上资源。

revving技术:不频繁更新的文件会使用特定的命名方式:在URL后(通常是文件名后)加上版本号。加上版本号后的资源就被视作一个完全新的独立资源,同时拥有一年甚至更长的缓存过期时长。弊端:所有引用这个资源的地方都需要更新链接。web开发者通常会采用自动化构建工具在实际工作中完成这些琐碎的工作。当低频更新的资源(js/css)变动了,只用在高频变动的资源文件(html)里做入口的改动。好处:同时更新两个缓存资源不会造成部分缓存先更新而引起新旧文件内容不一致。对于互相有依赖关系的css和js文件,避免这种不一致性是非常重要的。

·缓存验证

触发缓存验证:用户点击刷新按钮时;缓存的响应头信息里含有“Cache-control:must-revalidate”的定义;在浏览器偏好设置里设置Advanced->Cache为强制缓存验证。

在缓存的文档过期后,需要进行缓存验证或者重新获取资源。只有在服务器返回强校验器或者弱校验器时才会进行验证。

RTags:

缓存的一种强校验器,响应头是一个对用户代理(User Agent)不透明的值。对于像浏览器这样的HTTP UA,不知道ETag代表什么,不能预测它的值是多少。如果资源请求的响应头里含有ETag,客户端可以在后续的请求的头上带上If-None-Match来验证缓存。

Last-Modified响应头可以作为一种弱校验器。弱:只能精确到一秒。如果响应头里含有这个信息,客户端可以在后续的请求头上带上If-Modified-Since来验证缓存。

当向服务端发起缓存校验的请求时,服务端后返回200 ok表示返回正常的结果或者304 Not Modified(不返回body)表示浏览器可以使用本地缓存文件。304响应头也可以同时更新缓存文件的过期时间。

3月26日 周二 HTTP缓存、HTTP cookies

·带Vary的响应

Vary HTTP响应头决定了对于后续的请求头,如何判断是请求一个新的资源还是使用缓存的文件。

当缓存服务器收到一个请求,只有当前的请求和原始(缓存)的请求头跟缓存的响应头里的Vary都匹配,才能使用缓存的响应。

使用vary头有利于内容服务的动态多样性。

Vary: User-Agent

缓存服务器需要通过UA(用户代理)判断是否使用缓存的页面。如果需要区分移动端和桌面端的展示内容,利用这种方式就能避免在不同的终端展示错误的布局。并且可以帮助搜索引擎更好地发现页面的移动版本。

·HTTP Cookie

又称Web Cookie、浏览器Cookie。是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态,Cookie使基于无状态的HTTP协议记录稳定的状态信息成为了可能。

Cookies主要的作用:

a.会话状态管理(如用户登录状态、购物车、游戏分数等其它需要记录的信息)

b.个性化设置(如用户自定义设置、主题等)

c.浏览器行为跟踪(如跟踪分析用户行为)

为何Cookie不用户客户端数据存储?

因为服务器指定Cookie后,浏览器的每次请求都会携带Cookie数据,会带来额外的性能开销(尤其是移动环境下)。新的浏览器API已经允许开发者直接将数据存储在本地。

·创建Cookie

当服务器收到HTTP请求时,服务器可以在响应头里面添加一个Set-Cookie选项。浏览器收到响应后通常会保存下Cookie,之后对该服务器每一次请求中都通过Cookie请求头将Cookie信息发送给服务端。Cookie的过期时间、域、路径、有效期、使用网站都可以指定。

Set-Cookie: <cookie名>=<cookie值> -------------服务器端Set-Cookie响应头部

·会话期Cookie

仅在会话期内有效,浏览器关闭后它会自动删除。因此会话期它不需要指定过期时间(Expires)或有效期(Max-age)。但是有些浏览器提供了会话恢复功能,即保存下会话期Cookie。

·持久性Cookie

可以指定一个Expires或Max-Age。

Set-Cookie:id=<...>;Expires:<...> ————过期时间设定的日期和时间只与客户端相关

·Cookie的Secure和HTTPOnly标记

标记为Secure的Cookie只应通过被HTTP协议加密过的请求发送给服务端。但敏感信息不应通过Cookie传输,Cookie有与其固有的不安全性,如果包含服务端Session信息的Cookie不想被客户端JS脚本调用,就应设置为HTTPOnly标记。

·Cookie的作用域

作用域——即Cookie应该发送给哪些URL。

Domain标识指定了哪些主机可以接受Cookie。默认为当前文档的主机(不包含子域名)。但指定了,则一般包含子域名。

Path标识指定了主机下的哪些路径可以接受Cookie(该URL路径必须存在于请求URL中)。以“/”为路径分隔符,子路径也会被匹配。

·JS通过Document.cookies访问Cookie

document.cookie="..."  ----------通过该属性可创建新的Cookie,也可通过该属性访问非HTTPOnly标记的Cookie。

·安全

当机器处于不安全环境时,切记不能通过HTTP Cookie存储、传输敏感信息。

会话劫持和XSS:在Web应用中,Cookie常用来标记用户和授权对话。因此如果Web应用的Cookie被窃取,可能导致授权用户的会话受到攻击。常用的窃取Cookie方法有利用社会工程学攻击和利用应用程序漏洞进行XSS攻击。HTTPOnly类型的Cookie由于阻止了JS对其的访问性能而能在一定程度上缓解此类攻击。

跨站请求伪造(CSRF):例如在不安全聊天室或论坛上的一张图片,实际上是一个给你银行服务器发送提现的请求。因为如果你之前已登陆了银行账户并且Cookie仍然有效(还没有其他验证步骤),钱就会被转走。阻止办法:对用户输入进行过滤、任何敏感操作都需要确认、用于敏感信息的Cookie只能拥有较短的生命周期等。

·追踪和隐私

第三方Cookie:每个Cookie都有与之相关联的域(Domain),如果Cookie的域和页面的域相同,那么我们称这个Cookie为第一方Cookie(first-party cookie),如果不同,则称之为第三方Cookie(third-party cookie)。一个页面包含图片或存放在其他域上的资源(如图片广告),第一方的Cookie也只会发送给设置它们的服务器。通过第三方组件发送的第三方Cookie主要用于广告和网络追踪。

禁止追踪:Do-Not-Track

僵尸Cookie:即删不掉的Cookie,删除后甚至会自动重建。

3月27日 周三 HTTP访问控制(CORS)

跨域资源共享(CORS)是一种机制,它使用额外的HTTP头来告诉浏览器,让运行在一个origin(domain)上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域HTTP请求。

·跨域共享标准允许下列场景中使用跨域HTTP请求:

a.由XMLHttpRequest或Fetch发起的跨域HTTP请求

b.Web字体(CSS中通过@font-face)

c.WebGL贴图

d.使用drawImage将Images/video画面绘制到canvas

e.样式表(使用CSSOM)

·功能概述

跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。规范要求,对那些可能对服务器数据类型产生副作用的HTTP请求方法(特别是GET以外的HTTP请求或者搭配某些MIME类型的POST请求),浏览器必须首先使用OPTIONS方法发起一个预检请求,从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的HTTP请求。在预检请求返回中,服务端也可以通知客户端,是否需要携带身份凭证(包括Cookies和HTTP认证相关数据)。

3月28日 周四 HTTP访问控制(CORS)

·三个访问控制示例

(未记录发送请求的条件)

1.简单请求

不会触发CORS预检请求的请求。(如使用了GET、HEAD、POST方法;请求中任意XMLHTTPRequestUpload对象均没有注册任何事件监听器;XMLHTTPRequestUpload对象可以使用XMLHTTPRequest.upload属性访问;请求中没有ReadableStream对象...)

HTTP请求首部:Origin:<请求来源>

HTTP响应首部:Access-Control-Allow_Origin: <该资源允许哪些外域访问>

2.预检请求

需预检的请求必须首先使用OPTIONS方法(HTTP/1.1 用以从服务器获取更多信息,不会对服务器资源产生影响)发起一个预检请求到服务器,以获知服务器是否允许该实际请求。预检请求的使用可以避免跨域请求对服务器用户数据产生的未预期的影响。(如请求包含自定义的请求首部字段;请求的Content-Type不属于application/x-www-form-urlencoded、multipart/form-data、text/plain...)

预检请求:

//告知服务器实际请求将使用POST方法

Access-Control-Request-Method: POST 

//告知服务器实际请求将携带两个自定义首部字段X-PINGOTHER, Content-Type,服务器据此决定,该实际请求是否被允许

Access-Control-Request-Headers: X-PINGOTHER, Content-Type

预检请求响应:

//服务器允许客户端使用POST,GET,OPTIONS方法发起请求,该字段仅限于在需要访问控制中的场景中使用

Access-Control-Allow-Methods: POST, GET, OPTIONS

//服务器允许请求中携带字段...

Access-Control-Allow-Headers: X-PINGOTHER, Content-Type

//该响应的有效时间为86400秒(24小时),在有效时间内,浏览器无须为同一请求再次发起预检请求。浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

Access-Control-Max-Age: 86400

3.附带身份凭证的请求

Fetch和CORS可以基于HTTP cookies和HTTP认证信息发送身份凭证。

//实现向服务器发送Cookies。如果服务器端的响应中未携带Access-Control-Allow-Credentials: true,浏览器将不会把响应内容返回给请求的发送者。

invocation.withCredentials = true; 

️对于附带身份凭证的请求,服务器不得设置Access-Control-Allow-Origin 的值为“*”(该资源可以被任意外域访问)因为请求的首部中携带了Cookie信息,如果设置了请求将会失败。

3月29日 周五 HTTP访问控制(CORS),HTTP的发展

HTTP响应首部字段

origin参数的值指定了允许访问该资源的外域URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。如果服务端制定了具体的域名而非*,那么响应首部中的Vary字段的值必须包括Origin,这将告诉客户端:服务端对不同的源站返回不同的内容。

Access-Control-Allow-Origin: <origin>|*

在跨域访问时,XMLHTTPRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头(Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma),如要访问其他头,则需要服务器设置本响应头。

Access-Control-Expose-Headers:<...>

指定了preflight(预检)请求的结果能够被缓存多久

Access-Control-Max-Age: <delta-seconds>

指定了当浏览器的credentials设置为true时是否允许浏览器读取response内容。当用在对preflight请求的响应中它指定了实际的请求是否可以使用credentials。

Access-Control-Allow-Credentials: true

用于预检请求的响应,指明了实际请求所允许使用的HTTP方法

Access-Control-Allow-Methods: <method>[,<method>]*

用于预检请求的响应,指明了实际请求中允许携带的首部字段

Access-Control-Allow-Headers: <field-name>[,<field-name]*

HTTP请求首部字段

预检请求或实际请求的源站,参数为源站URI,不包含任何路径信息,只是服务器名称

Origin:<origin>

用于预检请求,将实际请求所使用的HTTP方法告诉服务器

Access-Control-Request-Method: <method>

用于预检请求,将实际请求所携带的首部字段告诉服务器。

Access-Control-Request-Headers: <field-name>[,<field-name>]*

HTTP/2在HTTP/1.1几处基本的不同

HTTP/2是二进制协议而不是文本协议。不再可读,也不可无障碍的手动创建,改善的优化技术现在可被实施。

这是一个复用协议。并行的请求能在同一个链接在处理,移除了HTTP/1.x中顺序和阻塞的约束。

压缩了headers。因为headers在一系列请求中常常是相似的,其移除了重复和传输重复数据的成本。

其允许服务器在客户端缓存中填充数据,通过一个叫服务器推送的机制来提前请求。

3月30日 周六 HTTP消息

HTTP消息是服务器和客户端之间交换数据的方式。有两种类型的消息︰ 请求--由客户端发送用来触发一个服务器上的动作;响应--来自服务器的应答。

HTTP请求和响应具有相似的结构:

起始行:描述要执行的请求、对应的状态(成功或失败)。总是单行。

可选的HTTP头集合:指明请求或描述消息正文。

空行:指示所有关于请求的元数据已经发送完毕。

可选的包含请求相关数据的正文或响应相关的文档:正文的大小有起始行的HTTP头来指定。

HTTP请求

起始行

a.一个HTTP方法:如GET/PUT/POST/HEAD/OPTIONS,描述要执行的动作。GET表示要获取资源,POST表示向服务器推送数据。

b.请求目标:通常是一个URL或者是协议、端口和域名的绝对路径

c.HTTP版本

Headers

Body:不是所有请求都有一个body,例如获取资源的请求GET,HEAD,DELETE,OPTIONS不需要,有些请求将数据发送到服务器以便更新数据:常见POST请求(包含HTML表单数据)。

HTTP响应

状态行(起始行)

a.协议版本

b.状态码:常见200,404,302

c.状态文本:一个简短纯粹的信息,通过状态码的文本描述帮助人们理解该HTTP信息。

Headers

Body:不是所有响应都有body,如具有状态码的响应,通常不会有body。

HTTP/2帧

HTTP/1.x报文性能缺陷:

a.Header不像body,不会被压缩。

b.两个报文之间的header通常非常相似,但它们仍然在连接中重复传输。

c.无法复用。当在同一个服务器打开几个连接时:TCP热连接比冷连接更加有效。

HTTP/2新的引入:

将HTTP/1.x消息分成帧并嵌入到流中。数据帧和报头帧分离,从而允许报头压缩。将多个流组合,这是一个被称为多路复用的过程,它允许更有效的底层TCP连接。

HTTP/2 帧机制是在 HTTP/1.x 语法和底层传输协议之间增加了一个新的中间层,而没有从根本上修改它,即它是建立在经过验证的机制之上。

3月31日 周日 典型的HTTP会话

会话三阶段(如HTTP此类CS协议)

客户端建立一条TCP连接(如果传输层不是 TCP,也可以是其他适合的连接)。

客户端发送请求并等待应答。

服务器处理请求并送回应答,回应包括一个状态码和对应的数据。

从 HTTP/1.1 开始,连接在完成第三阶段后不再关闭,客户端可以再次发起新的请求。这意味着第二步和第三步可以连续进行数次。

建立连接

连接由客户端发起建立,在HTTP中打开连接意味着在底层传输层启动连接,通常是 TCP。

使用TCP时,HTTP服务器默认端口号是80。

️CS模型不允许服务器在没有显示请求时发送数据给客户端,为了解决这一问题,有若干技术:例如,使用XMLHTTPRequest 或 Fetch API 周期性地请求服务器,使用HTML WebSockets API等。

发送客户端请求

a.请求方法及请求参数

b.HTTP首部,为服务器提供关于所需数据的信息,或是一些改变请求行为的数据(如当数据已经被缓存,就不再应答)。以空行结束。

c.可选数据块,主要被POST方法使用

服务器响应结构

a.状态行

b.HTTP首部,为客户端提供关于所发送数据的一些信息(如类型,数据大小,使用的压缩算法,缓存指示)。以空行结束。

c.数据块,包含了相应的数据(如果有的话)。

响应状态码

200:OK

301:Moved Permanently,请求资源的URI已被改变。

404:Not Found

️URL:Uniform/Universal Resource Locator ,统一资源定位符,子类。

    URI:Uniform Resource Identifier 的缩写,统一资源标识符,代表一种标准,父类。

二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。而 URL 同时说明要如何访问这个资源。

上一篇下一篇

猜你喜欢

热点阅读