HTTP协议属于应用层协议。
Status Code,常见的有:
2**,OK,比如200 - 请求成功
3**,重定向,比如:
301 - 永久转移到其它URL
302 - 临时转移到其他URL
区分301和302还是有一定的SEO(搜索引擎优化)价值的,详见后文。
4**,比如404 - 请求的资源(网页等)不存在
5**,比如500 - 服务器错误或异常等
重定向
Redirect的实质是:
服务器发送一个Response到客服端,其中包含了重定向的指示
客户端根据重定向指示,再自动向重定向页面发送一个GET请求
服务器响应新的GET请求,再发送一个reponse给客户端
HTTP超文本传输协议的主要特点:
限制每次连接只能处理一个请求
,每次请求一次,释放一次连接。所以无连接表示每次连接只能处理一个请求。优点就是节省传输时间,实现简单。我们有时称这种无连接为短连接。对应的就有了长链接,长连接专门解决效率问题。当建立好了一个连接之后,可以多次请求。但是缺点就是容易造成占用资源不释放的问题。当HTTP协议头部中字段Connection:keep-alive表示支持长链接。你以为服务器(网站程序)会一直记得你,只要你不关闭浏览器,它都一直守着你等着你——错!
对服务器而言,它只是埋头干活:
接收一个请求(Request)
处理……
给客户端一个响应(Response)
中断连接,忘掉之前所有的一切
接收下一个请求(Request)
处理……
给客户端一个响应(Response)
中断连接,忘掉之前所有的一切
……
换言之,对服务器而言,每一次的请求都是独立的。
HTTP协议并不要求服务器端记录每一次的请求是“究竟是由谁”发起的,从而对相同“源地址”的请求采取任何特定措施……所以说,HTTP是一种简单的非连接无状态协议
@想一想@:为什么呢?
历史原因:当初HTTP协议就用来浏览个网页啥的,也没想到今天有这么复杂的需求啊
性能考虑:阅后即焚,是不是可以尽可能的释放服务器的性能消耗
名字+ : (分号) + 空格 + 值
,用来设置HTTP请求的一些参数。例如:Host请求消息的第一行为请求消息行,
GET /test/test.html HTTP/1.1
GET为请求方式,请求方式分为:Get(默认)、POST、DELETE、HEAD等
GET:明文传输 不安全,数据量有限,不超过1kb
POST:暗文传输,安全。数据量没有限制。
/test/test.html为URI,统一资源标识符
HTTP/1.1为协议版本
2 .请求消息头
从第二行开始到空白行统称为请求消息头
Accept:浏览器可接受的MIME类型 ,告诉服务器客户端能接收什么样类型的文件。
Accept-Charset:浏览器通过这个头告诉服务器,它支持哪种字符集
Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip
Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。 可以在浏览器中进行设置。
Host:初始URL中的主机和端口
Referrer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面
Content-Type:内容类型
告诉服务器浏览器传输数据的MIME类型,文件传输的类型
If-Modified-Since:利用这个头与服务器的文件进行比对,如果一致,则从缓存中直接读取文件
User-Agent:浏览器类型.
Content-Length:表示请求消息正文的长度
Connection:表示是否需要持久连接。如果服务器看到这里的值为“Keep -Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接
Cookie:用于分辨两个请求是否来自同一个浏览器,以及保存一些状态信息,
Date:请求时间GMT
1.响应消息行:第一行响应消息为响应消息行
HTTP/1.1 200 OK
HTTP/1.1为协议版本
200为响应状态码,常用的响应状态码有40余种,这里我们仅列出几种,详细请看:
200:一切正常
302/307:临时重定向
304:未修改,客户端可以从缓存中读取数据,无需从服务器读取
404:服务器上不存在客户端所请求的资源
500:服务器内部错误
OK为状态码描述
2.响应消息头
Location:指示新的资源的位置,通常和302/307一起使用,完成请求重定向
Server:指示服务器的类型
Content-Encoding:服务器发送的数据采用的编码类型
Content-Length:告诉浏览器正文的长度
Content-Language:服务发送的文本的语言
Content-Type:服务器发送的内容的MIME类型
Last-Modified:文件的最后修改时间
Refresh:指示客户端刷新频率,单位是秒
Content-Disposition:指示客户端下载文件
Set-Cookie:服务器端发送的Cookie
Expires:-1
Cache-Control:no-cache (1.1)
Pragma:no-cache (1.0) 表示告诉客户端不要使用缓存
Connection:close/Keep-Alive
Date:请求时间
3.消息正文
当请求方式是POST方式时,才能看见消息正文,
消息正文就是要传输的一些数据,如果没有数据需要传输时,消息正文为空。
HTTP是无状态的
你说,不对!我登录一起帮之后,它能怎么记住我耶……
这是因为引入了cookie:
在浏览器中保存的
以键值(名值,key-value)对形式存在的一小块数据,
它会随着HTTP请求、自动地在服务器和浏览器之间传输。
为不同的用户(客户端),生成不同的cookie,就可以区别/记住这些用户。
登录的实质就是:生成一个能够证明用户身份的cookie,比如:用户名或用户Id
除了基本的名值,cookie一般可以设置:
作用域:domain
默认是作用于当前域名,比如17bang.ren;
且不能跨域,即:17bang.ren下面的cookie不能在zyfei.com中使用;也不能在17bang.ren下面设定一个zyfei.com域名下的cookie;(@想一想@:为什么?)
但域名包含其下所有子域名,比如17bang.ren下面的cookie就可以用于sample.17bang.ren和doc.17bang.ren;
但两个兄弟子域名之间不能通用,比如sample.17bang.ren下的cookie就不能在doc.17bang.ren中使用
路径:path同一域名下,/Article 和 /Suggest 是不同的路径,默认为根路径,即所有路径下都有效
过期时间:expire
默认是会话期间有效,即关闭浏览器,cookie失效
也可以指定一个失效时间,比如2021年11月7日 12点30分25秒
expire注意:因为cookie是保存在浏览器端的,所以cookie是不能在服务器端被直接删除的,要想删除某个cookie,需要通过设置其过期时间为之前时间的方式实现。
security:默认为false,http可以;设置为true,仅https下可用
httponly:设置为true,仅服务器端可用;默认为false,JavaScript等浏览器脚本语言也可用
但cookie的使用,带来了很多问题:
隐私泄露
道理很简单,通过cookie,我作为一个购物网站,可以很方便的记录你:
浏览了哪些商品,
哪些商品页浏览得最频繁
在哪个商品页面停留最久
……
所以你上午在淘宝看了一本《成就顶级大佬,跟飞哥学编程》和一顶棒球帽,下午就会给你一个植发的广告, ̄へ ̄,这啥意思啊?
其实相对于使用浏览器的网站,APP才是隐私泄露的重灾区!浏览器在一诞生就受到了较严格的隔离,很多事情(比如查看本地文件、获取用户地址、录音……)操作系统是不给它权限的,或者至少要得到用户同意。但你安装APP的时候,就不得不一个一个的同意,然后……
安全漏洞
首先,cookie本身是由浏览器控制的,如果你的电脑被黑客入侵,哦豁~,ʅ(‾◡◝)ʃ,当然如果要杜绝这种隐患,我们要不要使用cookie(使用其他登录技术,比如U盾啥的);既然使用cookie就不考虑这种情形了……
体会:安全防护是有极限/边界的
其次,cookie是以明文(未加密)文本形式存在,所以是非常容易泄露/篡改/伪造的,需要开发人员自己处理。开发人员的水平自然是参差不齐的,所以……
演示:F12修改cookie值/禁用cookie
最后,还有很多很多“聪明人”的奇巧淫技,详见后文。
Session
严格来说,Session并不属于HTTP协议,但目前它已经非常流行,形成一种事实上必知必会的技术。
Cookie是通过客户端保持状态的解决方案。从定义上来说,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端
,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。
让我们说得更具体一些:当用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体(Response Body)中的,而是存放于HTTP响应头(Response Header);当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置,对于Windows操作系统而言,我们可以从: [系统盘]:\Documents and Settings[用户名]\Cookies
目录中找到存储的Cookie;自此,客户端再向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,**Cookie信息则存放在HTTP请求头(**Request Header)了。
有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。通常,我们可以从很多网站的登录界面中看到“请记住我”这样的选项,如果你勾选了它之后再登录,那么在下一次访问该网站的时候就不需要进行重复而繁琐的登录动作了,而这个功能就是通过Cookie实现的。
与Cookie相对的一个解决方案是Session,它是通过服务器来保持状态的。
由于Session这个词汇包含的语义很多,因此需要在这里明确一下 Session的含义。
首先,我们通常都会把Session翻译成会话,因此我们可以把客户端浏览器与服务器之间一系列交互的动作称为一个 Session。从这个语义出发,我们会提到Session持续的时间,会提到在Session过程中进行了什么操作等等;
其次,Session指的是服务器端为客户端所开辟的存储空间,在其中保存的信息就是用于保持状态。从这个语义出发,我们则会提到往Session中存放什么内容,如何根据键值从 Session中获取匹配的内容等。
要使用Session,第一步当然是创建Session了。那么Session在何时创建呢?当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法。
在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;当客户端再次发送请求的时候,会将这个Session id带上,服
务器接受到请求之后就会依据Session id找到相应的Session,从而再次使用之。正是这样一个过程,用户的状态也就得以保持了。
给每个session分配一个唯一的sessionid 并通过cookie发送给客户端,让客户端发起新的请求的时候,将在cookie头中携带这个JsessionID
,这样服务器能找到客户端对应的session。
URL回写是指服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID
带会服务器。如果直接在浏览器输入服务端资源的url来请求该资源,那么Session是匹配不到的。
Tomcat对Session的实现,是一开始同时使用Cookie和URL回写机制,如果发现客户端支持Cookie,就继续使用Cookie,停止使用URL回写。如果发现Cookie被禁用,就一直使用URL回写。jsp开发处理到Session的时候,对页面中的链接记得使用response.encodeURL() 。
另外:
session把主要数据存放在服务器端,
只把SessionID存放在cookie中来回传递(Id:独一无二的身份标记)
服务器通过SessionId定位session中存放的数据。
相对于cookie,Session可以:
存放大量的不同格式的数据,不会有流量负担
存放敏感数据,不会泄露到客户端
但Session的问题是:
占用大量内存(或其他存储空间),需要额外的运算(比如通过SessionId查找)
可能会丢失:为了节约存储空间,Session一般都会设置过期(expire)时间,过期时间一到就自动删除;但有时候,如果内存不够用或其他原因,Session也有可能在过期时间到来之前被删除……
参考: