后浪笔记一零二四

1. Cookie

  1. Cookie是什么? RFC6265,HTTP State Management Mechanism

保存在客户端、由浏览器维护、表示应用状态的HTTP头部

  • 存放在内存或者磁盘中
  • 服务器端生成Cookie在响应中通过Set-Cookie头部告诉客户端(允许多个Set-Cookie头部传递多个值)
  • 客户端得到Cookie后,后续请求都会自动将Cookie头部携带至请求中。
client                                           server
   |                                               |
   |----GET http://www.example.com/ HTTP/1.1------>|
   |                                               |
   |<----------------------------------------------|
   |          HTTP/1.1 200 OK                      |
   |          Set-Cookie: session-id=12345;        |
   |                                               |
   |---------------------------------------------->|
   | GET http://www.example.com/ HTTP/1.1          |
   | Cookie: session-id=12345;                     |
  1. Cookie头部和Set-Cookie头部的abnf定义
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 一个请求头部只能带一个Cookie头部
cookie-header = "Cookie:" OWS cookie-string OWS
    cookie-string = cookie-pair *(";" SP cookie-pair)
         cookie-pair = cookie-name "=" cookie-value

# 一个响应头部可以带多个Set-Cookie头部
set-cookie-header = "Set-Cookie:" SP set-cookie-string
   set-cookie-string = cookie-pair *(";" SP cookie-av)
      cookie-pair = cookie-name "=" cookie-value
      cookie-av: 描述cookie-pair的可选属性

cookie-av = expires-av / max-age-av / domain-av / path-av / secure-av / httponly-av / extension-av
    * expires-av = "Expires=" sane-cookie-date
          cookie到日期sane-cookie-date后失效
    * max-age-av = "Max-Age=" non-zero-digit *DIGIT
          cookie经过*DIGIT秒后失效。max-age优先级高于expires
    * domain-av = "Domain=" domain-value
          指定cookie可用于哪些域名,默认可以访问当前域名
    * path-av = "Path=" path-value
          指定Path路径下才能使用cookie
    * secure-av = "Secure"
          只有使用TLS/SSL协议(https)时才能使用cookie
    * httponly-av = "HttpOnly"
          不能使用JavaScript (Document.cookie, XMLHttpRequest, Request APIs) 访问到cookie
  1. Cookie使用的限制
  • RFC规范对浏览器使用Cookie的要求 每条Cookie的长度(包括name,value以及描述的属性等总长度)至少要支持4KB 每个域名下至少支持50个Cookie 至少要支持3000个Cookie
  • 代理服务器传递Cookie时会有限制 很多代理服务器会限制http的头部的长度为4KB,8KB,而nginx默认是32KB 所以,生成cookie的Origin Server应当减少每个cookie的大小
  1. Cookie在协议设计上的问题
  • Cookie会被附加在每个HTTP请求中,所以无形中增加了流量
  • 由于在HTTP请求中的Cookie是明文传递的,所以安全性成问题(除非使用HTTPS)
  • Cookie的大小不应超过4KB,故对于复杂的存储需求来说是不够用的。

2. Session

  1. 登录场景下Cookie与Session的常见用法
       浏览器                                       服务器
          |                                            |
          |----1.POST /login-------------------------->|---2.验证用户信息--->DB
          |                                            |        V
          |<---4.200 OK--------------------------------|  3.验证通过,将有时效
5.按时限保|      Set-Cookie:session=xxx                |  的登录状态写入Redis
存cookie  |                                            |                  \
          |                                            |                   >Redis
          |----6.GET /profile------------------------->|7.解析session        /
          |      Cookie:session=xxx                    |并对比资源状态----->-
          |                                            |     V
          |                                            | 8.执行业务
          |<---9.200 OK--------------------------------|
  1. 无状态的REST架构 VS 状态管理
  • 应用状态与资源状态 应用状态:应由客户端管理,不应由服务器管理 如浏览器目前在哪一页 REST架构要求服务器不应保持应用状态 资源状态:应由服务器管理,不应由客户端管理 如数据库中存放的数据状态,例如用户的登录信息
  • HTTP请求的状态 有状态的请求:服务器端保存请求的相关信息,每个请求可以使用以前保留的来请求相关信息 服务器session机制使服务器保存请求的相关信息 cookie使请求可以携带查询信息,与session配合完成有状态的请求 无状态的请求:服务器能够处理的所有信息都来自当前请求所携带的信息 服务器不会保存session信息 请求可以通过cookie携带
  1. 第三方Cookie 浏览器允许跨域响应的响应头Set-Cookie,并在后续访问该域时自动使用Cookie
    1. 用户踪迹信息的搜集

3. 同源策略

3.1 浏览器为什么要有同源策略

  1. 为什么需要同源策略 同一个浏览器发出的请求,未必都是用户自愿发出的请求 只有page.html是用户发出的,其他请求是浏览器自动发出的。 站点domain-b.com收到的来自同一个浏览器的请求,可能来自于站点domain-a.com的。

  2. 没有同源策略下的Cookie 只能保证用户请求来自于同一浏览器,不能确保是用户自愿发出的。

    • 访问站点A后,站点A通过Set-Cookie: XXXX头部将Cookie返回给浏览器
    • 浏览器会保存Cookie,留待下次访问
    • 站点B的脚本访问站点A时,浏览器会自动将Cookie:cookie添加到请求的头部访问站点A,提升用户体验
    • 站点A的鉴权策略:取出Cookie值与数据库或者缓存中的token验证,通过后将数据赋予请求继续处理。
  3. 如果没有同源策略 站点B的脚本就可以随意修改站点A的DOM结构

  4. 浏览器的同源策略 限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互

URL 结果 原因
http://store.company.com/dir2/other.html 成功 只有路径不同
http://store.company.com/dir/inner/another.html 成功 只有路径不同
https://store.company.com/secure.html 失败 不同协议(https和http)
http://store.company.com:81/dir/etc.html 失败 不同端口
http:///news.company.com/dir/other.html 失败 不同域名
  1. 安全性与可用性需要一个平衡点
可用性: HTML的创作者决定跨域请求是否对本站点安全
     <script><img><iframe><link><video><audio> 带有src属性可以跨域访问
     允许跨域写操作: 例如表单提交或者重定向请求
             CSRF安全性问题
安全性: 浏览器需要防止站点A的脚本访问站点B发起危险动作
     Cookie、LocalStorage和IndexDB无法读取
     DOM无法获得(防止跨域脚本篡改DOM结构)
     AJAX请求不能发送
  1. 跨站请求伪造攻击 Cross-Site Request Forgery(CSRF)

3.2 如何"合法"地跨域访问?

同源策略其实是阻止跨域访问的,这节课中我将会介绍CORS,它能够允许我们在浏览器中跨域访问。

  1. CORS: Cross-Origin Resoruce Sharing
  • 浏览器同源策略下的跨域访问解决方案: 如果站点A允许站点B的脚本访问其资源,必须在HTTP响应中显式的告知浏览器:站点B是被允许的 访问站点A的请求,浏览器应告知该请求来自站点B 站点A的响应中,应明确哪些跨域请求是被允许的 策略1: 何为简单请求? GET/HEAD/POST方法之一 仅能使用CORS安全的头部:Accept、Accept-Language、Content-Language、Content-Type Content-Type值只能是:text/plain、multipart/form-data、application/x-www.form-urlencoded三者其中之一。 策略2:简单请求以外的其他请求 访问资源前,需要先发起preflight预检请求(方法为OPTIONS)询问何种请求是被允许的
  1. 简单请求的跨域访问
  • 请求中携带Origin头部告知来自哪个域
  • 响应中携带Access-Control-Allow-Origin头部表示允许哪些域
  • 浏览器放行
  Client                                  Server
    |                                       |
    |Simple request                         |
    |-------------------------------------->|
    |GET /doc HTTP/1.1                      |
    |Origin: Server-b.com                   |
    |                                       |
    |<--------------------------------------|
    |               HTTP/1.1 200 OK         |
    |  Access-Control-Allow-Origin: Server-b|

Server必须回应一个头部,Access-Control-Allow-Origin: *,告诉浏览器,我允许哪些域访问我,比如*,表示允许任何域来访问我。 大家可能会认为,这一步有点多余,Client已经告诉Server,我来自于Server-b了,你server自然就可以决定,到底接不接受我的访问了,为什么还要反过来告诉Client呢? 其实我们限制能不能同源访问的,全部在Client,Server是不做任何限制的,即使你不传Origin头部,一般Server也不会有问题的,也还是会发给你响应的。也就是说,我们的浏览器肯定收到了响应了,但是如果这个Access-Control-Allow-Origin指定的这个域名,不是当前页面所匹配的域名的话呢,浏览器就不会去渲染这个响应的请求。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<html>
<body>
<p>本页面来自http://protocol.taohui.tech,将要通过ajax访问http://cross-origin.taohui.tech/access</p>
<p id="p1">从跨域请求得到的响应</p>
<script>
var invocation = new XMLHttpRequest();
var url = 'http://cross-origin.taohui.tech/access';

function handler() {
  if (invocation.readyState == 4) 
  {
    if (invocation.status == 200) {// 200 = OK
      console.log(invocation.responseText);
      document.getElementById("p1").innerHTML = invocation.responseText;
    }
  }
}
function callOtherDomain() {
  if (invocation) {
    invocation.open('GET', url, true);
    invocation.onreadystatechange = handler;
    invocation.send();
  }
}

callOtherDomain()
</script>
</body>
</html>

修改nginx配置,然后重启nginx:

server {
  server_name cross-origin.taohui.tech;
  default_type text/plain;

  location /login {
    add_header Set-Cookie 'session=success';
    return 200 'login success!';
  }

  location / {
    add_header Access-Control-Allow-Origin 'http://protocol.taohui.tech';
    return 200 '{"hello":"world"}';
  }
}
  1. 预检请求
  • 预检请求头部 Access-Control-Request-Method Access-Control-Request-Headers

  • 预检请求响应 Access-Control-Allow-Methods Access-Control-Allow-Headers Access-Control-Max-Age

            Client                                                    Server
              |                                                          |
              |--------------------------------------------------------->|
              |OPTIONS /doc HTTP/1.1                                     |
              |Origin: Server-b.com                                      |
              |Access-Control-Request-Method: POST                       |
              |Access-Control-Request-Headers:X-PINGOTHER,Content-Type   |
              |                                                          |
              |                                                          |
              |<---------------------------------------------------------|
              |                                         HTTP/1.1 200 OK  |
              |           Access-Control-Allow-Origin: http://foo.example|
              |    Access-Control-Allow-Headers: X-PINGOTHER,Content-Type|
              |                             Access-Control-Max-Age: 86400|
              |                                                          |
              |--------------------------------------------------------->|
              |POST /doc HTTP/1.1                                        |
              |X-PINGOTHER: pingpong                                     |
              |Content-Type: text/xml; charset=UTF-8                     |
              |Origin: Server-b.com                                      |
              |Access-Control-Request-Method: POST                       |
              |Access-Control-Request-Headers: X-PINGOTHER,Content-Type  |
              |                                                          |
              |<---------------------------------------------------------|
              |                                          HTTP/1.1 200 OK |
              |           Access-Control-Allow-Origin: http://foo.example|
              |                                                          |
  1. 跨域访问资源:请求头部 请求头部

    • Origin (RFC6454):一个页面的资源可能来自于多个域名,在AJAX等子请求中标明来源于某个域名下的请求,以通过服务器的安全校验 origin = “Origin:” OWS origin-list-or-null OWS origin-list-or-null = %x6E %x75 %x6C %x6C / origin-list origin-list = serialized-origin *(SP serialized-origin) serialized-origin = scheme “://” host[":" port]
    • Access-Control-Request-Method 在preflight预检请求(OPTIONS)中,告知服务器接下来的请求会使用哪些方法
    • Access-Control-Request-Headers 在preflight预检请求(OPTIONS)中,告知服务器接下来的请求会传递哪些头部
  2. 跨域访问资源:响应头部 响应头部

    • Access-Control-Allow-Methods * 在preflight预检请求的响应中,告知客户端后续请求允许使用的方法
    • Access-Control-Allow-Headers * 在preflight预检请求的响应中,告知客户端后续请求允许携带的头部
    • Access-Control-Max-Age * 在preflight预检请求的响应中,告知客户端该响应的信息可以缓存多久
    • Access-Control-Expose-Headers * 告知浏览器哪些响应头部可以供客户端使用,默认情况下只有Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma可供使用
    • Access-Control-Allow-Origin * 告知浏览器允许哪些域访问当前资源,*表示允许所有域。为避免缓存错乱,响应中需要携带Vary: Origin
    • Access-Control-Allow-Credencials * 告知浏览器是否可以将Credentials暴露给客户端使用,Credentials包含cookie、authorization类头部、TLS证书等。

4. HTTP协议的基本认证

对于资源的权限认证,是由服务器给到我们浏览器的一种输入用户名和密码的一种方式,然后在浏览器中提供一个ui界面由用户输入用户名和密码以后,再返回给服务器进行验证,服务器告诉我们结果,这样的一个流程。

我们可以看到这个流程比较复杂,但是有一种认证方式叫做基本认证,这是所有浏览器都提供的一个用户界面,标准的用户界面给到我们,这节课中我们将会介绍基本的认证流程。

  1. HTTP基本认证
  • RFC7235,一种基本的验证框架,被绝大多数浏览器所支持
  • 明文传输,如果不使用TLS/SSL传输则有安全问题
        Client                                                     Server
	        |                                                           |
	        |---------------------------------------------------------->|
	        |GET / HTTP/1.1                                             |
	        |                                                           |
	        |<----------------------------------------------------------|
	        |                                 HTTP/1.1 401 Unauthorized |
	        | WWW-Authenticate: Basic realm="Access to the staging site"|
	|-------|                                                           |
Ask user  |                                                           |
	|------>|                                                           |
	        |---------------------------------------------------------->|
	        |GET / HTTP/1.1                                             |
	        |Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW11              |----|
          |                                                           |  Check credentials
	        |                                                           |<---|
	        |<----------------------------------------------------------|
	        |                                     HTTP/1.1 200 OK       |
	        |                                                 OR        |
	        |                               HTTP/1.1 403 Forbidden      |
  1. 认证请求
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
* 在请求中传递认证信息: Authorization = credentials
   * credentials = auth-scheme [ 1*SP (token68 / #auth-param) ]
      * auth-scheme = token
      * token68 = 1*(ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"="
      * auth-param = token BWS "=" BWS ( token / quoted-string )
          * BWS = OWS
	      * OWS = *( SP/HTAB )
   * 例如: authorization: Basic ZGQ6ZWU=
      * 实际上ZGQ6ZWU=dd:ee的base64编码,表示用户名和密码
* 由代理服务器认证:Proxy-Authorization = credentials
  1. 认证响应
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
* 在响应头部中告知客户端需要认证:WWW-Authenticate = 1#challenge
    * challenge = auth-scheme [1*SP (token68 / #auth-param)]
        * auth-scheme = token
	* token68 = 1*(ALPHA / DIGIT / "-" / "_" / "~" / "+" / "/") *"="
	* auth-param = token BWS "=" BWS (token / quoted-string)
	    * BWS = OWS
	        * OWS = *(SP / HTAB)
    * 例如: www_authenticate: Basic realm="test auth_basic"
* 由代理服务器认证:Proxy-Authenticate = 1#challenge
* 认证响应码
    * 由源服务器告诉客户端需要传递认证信息: 401 Unauthorized
    * 由代理服务器认证: 407 Proxy Authentication Reuqired
    * 认证失败: 403 Forbidden

5. 网络爬虫

5.1 对待网络爬虫的2种态度

  1. 欢迎常光临
  • SEO(Search Engine Optimization),搜索引擎优化
    • “合法”的优化:sitemap、title、keywords、https等
    • “非法”的优化:利用PageRank算法漏洞

PageRank其实是谷歌早期发明的一种算法,那么我们怎样去判定,一个页面是用户想要的呢? 比如用户搜索了一个关键词,比如叫做"原子能",那么这里有很多相关的页面,每个页面就是一个笑脸。 每个页面中它可能引用了其他的一些知识,比如有个url链接,指向了一张图,或者指向了某个参考的文档。 那么当这个黄色的最大的笑脸,其实它是被最多的页面所引用的,url都指向它的时候,那么我们就认为这个是用户最想要的。 那么按照这个大小的排序,给用户展示,这样的排序结果,搜索结果,这就叫做PageRank算法。

PageRank算法的漏洞呢,比如说有些商家呢,它就会制造一些访问量非常大的站点,对于它在进行收费的这样的客户, 然后把自己很多的这个僵尸页面全部指向这个客户的页面,客户向它付费,它就可以通过这样的一种手段, 使得这个客户的这个页面排名较前,这样的话相关用户在百度等搜索引擎上去搜索的时候呢,就更容易搜索到这个客户的页面了。 这就是“非法”的优化。

  1. 拒绝访问
  • 为了对抗网络爬虫而生的图形验证码

为什么会拒绝访问呢?我们可以想象几种,在垂直领域进行网络爬虫爬取信息的场景。比如说,我们现在买机票的时候,像亚洲航空这样的航空公司呢,它会时不时的提供一些低价的机票,那么但是实际上我们用的人自己去搜的话,就很难去搜到,这是因为有一些代理商等,它拿着网络爬虫,不停的去爬取站点,模仿人类,当发现特价机票的时候,马上就先买下来,这样的话,需要的人肯定是买不到的。出行的比如说12306,还有微博上的僵尸粉,还有电商上的做比价,等等,这些站点对于网络爬虫都是非常不欢迎的,当非常不欢迎的时候,怎么办呢?

5.2 网络爬虫如何抓取数据呢

  1. 爬虫常见的请求头部
  • User-Agent: 识别是哪类爬虫
  • From: 提供爬虫机器人管理者的邮箱地址
  • Accept: 告知服务器爬虫对哪些资源类型感兴趣
  • Referer: 相当于包含了当前请求的页面URI
  1. robots.txt:告知爬虫哪些内容不应爬取
  • Robots exclusion protocol: http://www.robotstxt.org/orig.html 这个是非官方的,非正式的爬虫软件并不遵循这样的一个规则 但是向谷歌这样的爬虫等,它都是会遵循这样的一个规则的。
  • robots.txt文件内容
    • User-agent: 允许哪些机器人
    • Disallow: 禁止访问特定目录
    • Crawl-delay: 访问间隔秒数
    • Allow: 抵消Disallow指令
    • Sitemap: 指出站点地图的URI
                        Web机器人客户端                        www.joes-hardware.com
			                      |GET /robots.txt                         |
机器人对robots.txt文件进行  |--------------------------------------->|
解析,判断是否允许它访问    |<---file--------------------------------|
文件acetylene-torches.html  |GET /specials/acetylene-torches.html    |
                            |--------------------------------------->|
允许访问,继续发送请求      |<---file--------------------------------|
                            |                                        |

本文发表于 0001-01-01,最后修改于 0001-01-01。

本站永久域名「 jiavvc.top 」,也可搜索「 后浪笔记一零二四 」找到我。


上一篇 « 下一篇 »

赞赏支持

请我吃鸡腿 =^_^=

i ysf

云闪付

i wechat

微信

推荐阅读

Big Image