HTTP和HTTPS

HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法。

HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)简单讲是HTTP的安全版,在HTTP下加入SSL层。

HTTP和HTTPS均是由TCP协议封装而来,在进行http协议和https协议时,需要进行 三次握手和四次挥手。

SSL(Secure Sockets Layer 安全套接层)主要用于Web的安全传输协议,在传输层对网络连接进行加密,保障在Internet上数据传输的安全。
HTTP协议浅析 - 图1
HTTP三点注意事项:

  • HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
  • HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

客户端请求消息
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。下图给出了请求报文的一般格式:
HTTP协议浅析 - 图2
服务器响应消息
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文:
HTTP协议浅析 - 图3

Cookie、Session和Token的区别

前言:

HTTP是一种无状态的协议,为了分辨链接是谁发起的,需要浏览器自己去解决这个问题。不然有些情况下即使是打开同一个网站的不同页面也都要重新登录。而Cookie、Session和Token就是为了解决这个问题而提出来的两个机制。

用户通过浏览器登录一个网站,在该浏览器内打开网站其他页面时,不需要重新登录。而HTTP是无状态的协议,那么网站后端是如何判断用户已经登陆了呢?不同的网站,判断用户登录状态的方法都不一样。有的网站是通过session来验证用户的登录状态,有的网站是通过token来验证用户的登录状态,也有的网站是通过其他的方式来判断。本文讲了两个比较常用的方法,利用session或token来验证用户登录状态。

Cookie

Cookie:cookie是服务器发送给客户端的用于验证某一会话信息的数据,cookie中有很多字段。不同网站Cookie中字段是不一样的,是由服务器端设置的。Cookie中常放入session_id 或者 token 用来验证会话的登录状态。

Cookie为什么能验证登录状态?那是因为cookie中放入了session_id 值或者 token 值!

cookie的分类:

  • Session Cookie:key, value形式,过期时间可设置,如不设,则浏览器关掉就消失了,存储在内存当中,否则就按设置的时间来存储在硬盘上的,过期后自动清除
  • Permenent Cookie:Cookie的主要内容包括:名字,值,过期时间,路径和域等等

Session Cookie:

我们打开一个浏览器访问某个网站,该网站服务器就会返回一个Session Cookie,当我们访问该网站下其他页面时,用该Cookie验证我们的身份。所以,我们不需要每个页面都登录。但是,当我们关闭浏览器重新访问该网站时,需要重新登录获取浏览器返回的Cookie。Session Cookie在访问一个网站的过程中,一般是不变化的,有时也会变化,比如,切换不同的权限时,Cookie值会变化。

如下图,是Session Cookie的生成和作用 :
HTTP协议浅析 - 图4
在整个会话过程中,cookie主要的值是不变化的,某些值会变化。如图,是DVWA不同等级之间用户的Session cooke。
HTTP协议浅析 - 图5

Permenent Cookie:

是保存在浏览器客户端上存储用户登录信息的数据,Permenent Cookie是由服务器端生成,然后发送给User-Agent(一般是浏览器),浏览器会将Cookie保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie,大部分浏览器默认都是开启了cookie)。

例如,下面的截图是保存的baidu.com域名下的 Permenent Cookie。 HTTP协议浅析 - 图6

Session认证机制

Session:session是保存在服务器端的经过加密的存储特定用户会话所需的属性及配置信息的数据。当我们打开浏览器访问某网站时,session建立,只要浏览器不关闭(也有时间限制,可以自己设置超时时间),这个网站就可以记录用户的状态,当浏览器关闭时,session结束。

  • 浏览器第一次发送请求时,服务器自动生成了Session(用户会话所需的属性及配置信息),并且生成了Session ID来唯一标识这个Session,并将其通过响应发送到浏览器。浏览器第二次发送请求会将前一次服务器响应中的Session ID放在请求的Cookie中一并发送到服务器上,服务器从请求中提取出Session ID,并和保存的所有Session ID进行对比,找到这个用户所对应的Session,从而知道了用户的登录信息。一般Session ID会有时间限制,超时后毁掉这个值,默认30分钟。
  • 当用户在应用程序的 Web页间跳转时,也就是一次会话期间,浏览器不关闭时,Session ID是一直不变的。

HTTP协议浅析 - 图7 SessionID除了可以保存在Cookie中外,还可以保存在URL中,作为请求的一个参数(sid)。

Session的一些安全配置

  • session应该设置时效性,比如半个小时,当用户在半小时内未操作,即清除session。(时间)
  • 关闭浏览器,即清除session。(事件)
  • 如果应用为了用户体验,只要session一直在使用,则session不失效。这样,当用户cookie被盗后,可能导致session保持攻击。这样的做法是:

    1. (1) session设置一个时间,无论该session活动与否,都强制清除session。<br /> (2) 用户的IPUserAgent等信息变化后,强制清除session

Token认证机制

Token:Token是服务器端生成的用于验证用户登录状态的加密数据,和用session验证差不多。只不过Token验证服务器端不需要存储用户会话所需的配置等数据。只需要后端将Token进行验证签名,然后再发给浏览器。所以,使用Token进行验证,在一次会话中,Token值是不变化的,这和session一样。

HTTP协议浅析 - 图8
HTTP协议浅析 - 图9

Token预防CSRF

上面利用Token验证是将Token值放在Cookie中用来验证用户登录状态,而我们现在要利用Token来预防CSRF的话,就不能将Token值放在CSRF中了。我们可以如下做:

当我们访问的网页中含有需要修改数据的地方,后端服务器就会随机发送一个Token值给前端,然后我们修改完数据提交的请求包中,就会有该token字段,后端提取该token验证登录状态。当我们每次访问该网页或者其他修改数据的网页时,服务器端返回的Token值都是不同的,都是随机的。这样,可以有效预防CSRF。

Session认证和Token认证的区别

现在大多数网站用户认证都是基于 session 的,即在服务端生成用户相关的 session 数据,而发给客户端 sesssion_id 存放到 cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户认证。这种认证方式,可以更好的在服务端对会话进行控制,安全性比较高(session_id 随机),但是服务端需要存储 session 数据(如内存或数据库),这样无疑增加维护成本和减弱可扩展性(多台服务器)。CSRF 攻击一般基于 cookie 。
基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用户验证后,服务端生成一个 token(hash 或 encrypt)发给客户端,客户端可以放到 cookie 或 localStorage 中,每次请求时在 Header 中带上 token ,服务端收到 token 通过验证后即可确认用户身份。这种方式相对 cookie 的认证方式就简单一些,服务端不用存储认证数据,易维护扩展性强, token 存在 localStorage 可避免 CSRF 。不过这种方式在加密或解密的时候会有一些性能开销(好像也不是很大),有些对称加密存在安全隐患(aes cbc 字节翻转攻击)。

HTTP请求方法(Get/Post)

  1. 方法 描述
  2. GET Get长度限制为1024,特别快,不安全,在URL里可见,URL提交参数以?分隔,多个参数用&连接,请求指定的页面信息,并返回实体主体
  3. HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
  4. POST 长度一般无限制,由中间件限制,较慢,安全,URL里不可见。请求的参数在数据包的请求body
  5. PUT 向指定资源位置上传其最新内容
  6. DELETE 请求服务器删除指定的页面
  7. CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
  8. OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性
  9. TRACE 回显服务器收到的请求,主要用于测试或诊断

常见的URL编码(在url中)

  1. 空格 %20 %A0
  2. ' %27
  3. " %22
  4. # %23
  5. % %25
  6. & %26
  7. * %2A
  8. + %2B
  9. , %2C
  10. - %2D
  11. . %2E
  12. / %2F
  13. \ %5C
  14. = %3d
  15. 回车(\r) %0d
  16. 换行 (\n) %0a

GET和POST的区别

  • GET是从服务器上获取数据,POST是向服务器传送数据(功能不同)
  • GET请求参数显示,都显示在浏览器网址上,HTTP服务器根据该请求所包含URL中的参数来产生响应内容,即“Get”请求的参数是URL的一部分。例如:http://www.baidu.com/s?wd=Chinese(GET传参在url可显示,且传输长度有限制)
  • POST请求参数在请求体当中,消息长度没有限制而且以隐式的方式进行发送,通常用来向HTTP服务器提交量比较大的数据(比如请求中包含许多参数或者文件上传操作等),请求的参数包含在“Content-Type”消息头里,指明该消息体的媒体类型和编码.(POST传参隐藏,且传输长度没有限制)

一次HTTP请求的过程

  1. 当用户在浏览器的地址栏中输入一个URL并按回车键之后,浏览器会向HTTP服务器发送HTTP请求。HTTP请求主要分”为“Get”和“Post”两种方法。
  2. 当我们在浏览器输入URL http://www.baidu.com 的时候,浏览器发送一个Request请求去获取 http://www.baidu.com 的html文件,服务器把Response文件对象发送回给浏览器。(先访问html)
  3. 浏览器分析Response中的HTML,发现其中引用了很多其他文件,比如Images文件,CSS文件,JS文件。浏览器会自动再次发送Request去获取图片,CSS文件,或者JS文件。(然后访问html引用的文件)
  4. 当所有的文件都下载成功后,网页会根据HTML语法结构,完整的显示出来了。

一次请求(Request)和回复(Reply)的数据包

Request请求包

  1. GET /test/ HTTP/1.1
  2. Host: www.baidu.com
  3. Connection: keep-alive
  4. Pragma: no-cache
  5. Cache-Control: no-cache
  6. Upgrade-Insecure-Requests: 1
  7. User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
  8. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
  9. Referer: https://www.baidu.com/index.php
  10. Accept-Encoding: gzip, deflate, br
  11. Accept-Language: zh,zh-CN;q=0.8,ar;q=0.6,zh-TW;q=0.4
  12. Cookie: BAIDUID=AE4D1DA6B2D6689BB8C557B3436893E3:FG=1;BIDUPSID=AE4D1DA6B2D6689BB8C557B3436893E3; PSTM=1501466227;
  1. GET
    获取当前主机该路径下的数据
    HTTP/1.1是http协议的版本号

  2. Host (主机和端口号)
    Host:对应网址URL中的Web名称和端口号,用于指定被请求资源的Internet主机和端口号,通常属于URL的一部分。默认是80端口,如果是8080端口的话,则为:www.baidu.com:8080

  3. Connection (链接类型)
    Connection:表示客户端与服务连接类型
    1>当传输的数据较小时,可以一次传输完成时,Connection的值为close;
    2>当传输的数据较大时,不能一次性传输完成时,则数据需要分块传输,即把 Connection 的值设置为 keep-alive:
    (1)Client 发起一个包含 Connection:keep-alive 的请求
    (2)Server收到请求后:
    如果 Server 支持 keep-alive,回复一个包含 Connection:keep-alive 的响应,不关闭连接;
    如果 Server 不支持 keep-alive,回复一个包含 Connection:close 的响应,关闭连接。
    (3)如果client收到包含 Connection:keep-alive 的响应,向同一个连接发送下一个请求,直到一方主动关闭连接。keep-alive在很多情况下能够重用连接,减少资源消耗,缩短响应时间,比如当浏览器需要多个文件时(比如一个HTML文件和相关的图形文件),不需要每次都去请求建立连接。

  4. Upgrade-Insecure-Requests (升级为HTTPS请求)
    Upgrade-Insecure-Requests:升级不安全的请求,意思是会在加载 http 资源时自动替换成 https 请求,让浏览器不再显示https页面中的http请求警报。
    HTTPS 是以安全为目标的 HTTP 通道,所以在 HTTPS 承载的页面上不允许出现 HTTP 请求,一旦出现就是提示或报错。

  5. User-Agent (浏览器名称)
    User-Agent:是客户浏览器的名称

  6. Accept (接收的文件类型)
    Accept:指浏览器或其他客户端可以接受的MIME(Multipurpose Internet Mail Extensions(多用途互联网邮件扩展))文件类型,服务器可以根据它判断并返回适当的文件格式。
    举例:
    Accept: /:表示什么都可以接收。
    Accept:image/gif:表明客户端希望接受GIF图像格式的资源;
    Accept:text/html:表明客户端希望接受html文本。
    Accept: text/html, application/xhtml+xml;q=0.9, image/*;q=0.8:表示浏览器支持的 MIME 类型分别是 html文本、xhtml和xml文档、所有的图像格式资源。
    q是权重系数,范围 0 =< q <= 1,q 值越大,请求越倾向于获得其“;”之前的类型表示的内容。若没有指定q值,则默认为1,按从左到右排序顺序;若被赋值为0,则用于表示浏览器不接受此内容类型。
    Text:用于标准化地表示的文本信息,文本消息可以是多种字符集和或者多种格式的;
    Application:用于传输应用程序数据或者二进制数据。

  7. Referer (页面跳转处)
    Referer:表明产生请求的网页来自于哪个URL,用户是从该 Referer页面访问到当前请求的页面。这个属性可以用来跟踪Web请求来自哪个页面,是从什么网站来的等。
    有时候遇到下载某网站图片,需要对应的referer,否则无法下载图片,那是因为人家做了防盗链,原理就是根据referer去判断是否是本网站的地址,如果不是,则拒绝,如果是,就可以下载;

  8. Accept-Encoding(文件编解码格式)
    Accept-Encoding:指出浏览器可以接受的编码方式。编码方式不同于文件格式,它是为了压缩文件并加速文件传递速度。浏览器在接收到Web响应之后先解码,然后再检查文件格式,许多情形下这可以减少大量的下载时间。
    举例:Accept-Encoding:gzip;q=1.0, identity; q=0.5, *;q=0

如果有多个Encoding同时匹配, 按照q值顺序排列,本例中按顺序支持 gzip, identity压缩编码,支持gzip的浏览器会返回经过gzip编码的HTML页面。如果请求消息中没有设置这个域服务器假定客户端对各种内容编码都可以接受

  1. Accept-Language(语言种类)
    Accept-Langeuage:指出浏览器可以接受的语言种类,如en或en-us指英语,zh或者zh-cn指中文,当服务器能够提供一种以上的语言版本时要用到

  2. Cookie (Cookie)
    Cookie:浏览器用这个属性向服务器发送Cookie。Cookie是在浏览器中寄存的小型数据体,它可以记载和服务器相关的用户信息,也可以用来实现会话功能,以后会详细讲。

  3. Accept-Charset(字符编码)
    Accept-Charset:指出浏览器可以接受的字符编码。
    举例:Accept-Charset:iso-8859-1、gb2312、utf-8、ISO8859-1:通常叫做Latin-1。Latin-1包括了书写所有西方欧洲语言不可缺少的附加字符,英文浏览器的默认值是ISO-8859-1.
    gb2312:标准简体中文字符集;
    utf-8:UNICODE 的一种变长字符编码,可以解决多种语言文本显示问题,从而实现应用国际化和本地化。
    如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。

  4. Content-Type (POST数据类型)
    Content-Type:表示POST请求里用来表示的内容类型。一般有application/x-www-form-urlencoded,multipart/form-data,text/plain三种

  5. Pragma
    pragma是http/1.1之前版本的历史遗留字段,仅作为与http的向后兼容而定义。

规范定义的唯一形式:Pragme:no-cache 。只用于客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源。

  1. Cache-Control
    如果所有的中间服务器都实现以 HTTP/1.1为标准,那么直接使用 Cache-Control:no-cache 即可,如果不是的话,就要包含两个字段
    1. Cache-Control:no-cache
    2. Pragme:no-cache
  2. Fetch-Site系列
    Chrome 意欲在下一个版本 76 实现 Fetch Metadata请求头提案,该提案允许浏览器在发起请求时带上请求的相关上下文,使得服务器端可以进行安全相关的校验。提案的请求头包括
  • 请求目标 Sec-Fetch-Dest
  • 请求模式 Sec-Fetch-Mode(跨域规则与浏览上下文)
  • 是否跨域的 Sec-Fetch-Site
  • 是否用户触发的 Sec-Fetch-User。
  1. Fetch-Site系列
    Chrome 意欲在下一个版本 76 实现 Fetch Metadata请求头提案,该提案允许浏览器在发起请求时带上请求的相关上下文,使得服务器端可以进行安全相关的校验。提案的请求头包括
  • 请求目标 Sec-Fetch-Dest
  • 请求模式 Sec-Fetch-Mode(跨域规则与浏览上下文)
  • 是否跨域的 Sec-Fetch-Site
  • 是否用户触发的 Sec-Fetch-User。

Reply回复包

  1. HTTP/1.1 200 OK
  2. Date: Fri, 05 Oct 2018 01:35:48 GMT
  3. Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
  4. X-Powered-By: PHP/5.4.45
  5. Expires: Tue, 23 Jun 2009 12:00:00 GMT
  6. Cache-Control: no-cache, must-revalidate
  7. Pragma: no-cache
  8. Content-Length: 5212
  9. Connection: close
  10. Content-Type: text/html;charset=utf-8
  1. HTTP/1.1 200 OK
    1>HTTP/1.1 是http版本号
    2>200 OK 是状态码

    • 200 页面正常
    • 301、302 重定向
    • 400 http协议错误、401身份认证、403 禁止访问、404 页面不存在
    • 500 页面的动态代码有错误、502 响应超时
  2. Date: Fri, 05 Oct 2018 01:35:48 GMT
    服务器回复数据时的日期和时间

  3. Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
    服务器的Web服务器类型,中间件等

  4. Content-Length: 5212
    回复的数据包的长度

  5. Connection: close
    链接类型,不支持长链接,所以关闭

  6. Content-Type: text/html;charset=utf-8
    回复的数据类型,html格式的,utf8编码

HTTP Basic基本认证

BASIC认证概述


当一个客户端向HTTP服务器进行数据请求时,如果客户端未被认证,则HTTP服务器将通过基本认证过程对客户端的用户名及密码进行验证,以决定用户是否合法。客户端在接收到HTTP服务器的身份认证要求后,会提示用户输入用户名及密码,然后将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中, 如当用户名为anjuta,密码为:123456时,客户端将用户名和密码用“:”合并,并将合并后的字符串用BASE64加密为密文,并于每次请求数据时,将密文附加于请求头(Request Header)中。HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。

BASIC认证的过程

基本认证步骤:

  1. 客户端访问一个受http基本认证保护的资源。
  2. 服务器返回401状态,要求客户端提供用户名和密码进行认证。(验证失败的时候,响应头会加上WWW-Authenticate: Basic realm=”请求域”。)(401 Unauthorized WWW-Authenticate:Basic realm=”WallyWorld”)
  3. 客户端将输入的用户名密码用Base64进行编码后,采用非加密的明文方式传送给服务器。Authorization: Basic xxxxxxxxxx.
  4. 服务器将Authorization头中的用户名密码解码并取出,进行验证,如果认证成功,则返回相应的资源。如果认证失败,则仍返回401状态,要求重新进行认证。

优点:
基本认证的一个优点是基本上所有流行的网页浏览器都支持基本认证。基本认证很少在可公开访问的互联网网站上使用,有时候会在小的私有系统中使用(如路由器网页管理接口)。后来的机制HTTP摘要认证是为替代基本认证而开发的,允许密钥以相对安全的方式在不安全的通道上传输。

缺点:
虽然基本认证非常容易实现,但该方案建立在以下的假设的基础上,即:客户端和服务器主机之间的连接是安全可信的。特别是,如果没有使用SSL/TLS这样的传输层安全的协议,那么以明文传输的密钥和口令很容易被拦截。该方案也同样没有对服务器返回的信息提供保护。现存的浏览器保存认证信息直到标签页或浏览器被关闭,或者用户清除历史记录。HTTP没有为服务器提供一种方法指示客户端丢弃这些被缓存的密钥。这意味着服务器端在用户不关闭浏览器的情况下,并没有一种有效的方法来让用户登出。

特记事项:


1、Http是无状态的,同一个客户端对同一个realm内资源的每一个访问会被要求进行认证。
2、客户端通常会缓存用户名和密码,并和authentication realm一起保存,所以,一般不需要你重新输入用户名和密码。
3、以非加密的明文方式传输,虽然转换成了不易被人直接识别的字符串,但是无法防止用户名密码被恶意盗用。虽然用肉眼看不出来,但用程序很容易解密。