JavaScript学习 - Http报文简单解析及session和cookie的使用

HTTP请求报文解剖

HTTP请求报文由3部分组成(请求行+请求头+请求体):


下面是一个实际的请求报文:


①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。不过,当前的大多数浏览器只支持GET和POST。

②为请求对应的URL地址,它和报文头的Host属性组成完整的请求URL。

③是协议名称及版本号。

④是HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。

⑤ 是报文体,它将一个页面表单中的组件值通过param1=value1&param2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html?param1=value1&param2=value2”的方式传递请求参数。

对照上面的请求报文,我们把它进一步分解,你可以看到一幅更详细的结构图:


HTTP请求报文头属性

报文头属性是什么东西呢?我们不妨以一个小故事来说明吧。快到中午了,张三丰不想去食堂吃饭,于是打电话叫外卖:老板,我要一份“鱼香肉丝”,要12:30之前给我送过来,我在江湖湖公司研发部,叫张三丰。这里你要“鱼香肉丝”相当于HTTP报文体,而“12:30之前送过来”,你叫“张三丰”等信息就相当于HTTP的报文头。它们是一些附属信息,帮忙你和饭店老板顺利完成这次交易。

请求HTTP报文和响应HTTP报文都拥有若干个报文关属性,它们是为协助客户端及服务端交易的一些附属信息。

常见的HTTP请求报文头属性

Accept:请求报文可通过一个“Accept”报文头属性告诉服务端客户端接受什么类型的响应。如下报文头相当于告诉服务端,俺客户端能够接受的响应类型仅为纯文本数据:

Accept:text/plain

Accept属性的值可以为一个或多个MIME类型的值,关于MIME类型,大家请参考:http://en.wikipedia.org/wiki/MIME_type

Cookie:客户端的Cookie就是通过这个报文头属性传给服务端的哦!如下所示:

Cookie: $Version=1; Skin=new;jsessionid=5F4771183629C9834F8382E23BE13C4C

服务端是怎么知道客户端的多个请求是隶属于一个Session呢?注意到后台的那个jsessionid=5F4771183629C9834F8382E23BE13C4C木有?原来就是通过HTTP请求报文头的Cookie属性的jsessionid的值关联起来的!(当然也可以通过重写URL的方式将会话ID附带在每个URL的后面哦)。

Referer:表示这个请求是从哪个URL过来的,假如你通过google搜索出一个商家的广告页面,你对这个广告页面感兴趣,鼠标一点发送一个请求报文到商家的网站,这个请求报文的Referer报文头属性值就是http://www.google.com。

唐僧到了西天。如来问:侬是不是从东土大唐来啊?唐僧:厉害!你咋知道的!如来:呵呵,我偷看了你的Referer。很多貌似神奇的网页监控软件(如著名的我要啦),只要在你的网页上放上一段JavaScript,就可以帮你监控流量,全国访问客户的分布情况等报表和图表,其原理就是通过这个Referer及其它一些HTTP报文头工作的。

Cache-Control:对缓存进行控制,如一个请求希望响应返回的内容在客户端要被缓存一年,或不希望被缓存就可以通过这个报文头达到目的。如以下设置,相当于让服务端将对应请求返回的响应内容不要在客户端缓存:

Cache-Control: no-cache

其它请求报文头属性请参见:http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

如何访问请求报文头

由于请求报文头是客户端发过来的,服务端当然只能读取了,以下是HttpServletRequest一些用于读取请求报文头的API:

//获取请求报文中的属性名称
java.util.Enumeration<java.lang.String>   getHeaderNames();
//获取指定名称的报文头属性的值
java.lang.String getHeader(java.lang.String name)

由于一些请求报文头属性“太著名”了,因此HttpServletRequest为它们提供了VIP的API:

//获取报文头中的Cookie(读取Cookie的报文头属性)
 Cookie[]   getCookies() ;
//获取客户端本地化信息(读取 Accept-Language 的报文头属性)
java.util.Locale    getLocale()
//获取请求报文体的长度(读取Content-Length的报文头属性)
int getContentLength();

HttpServletRequest可以通过

HttpSession getSession()

获取请求所关联的HttpSession,其内部的机理是通过读取请求报文头中Cookie属性的JSESSIONID的值,在服务端的一个会话Map中,根据这个JSESSIONID获取对应的HttpSession的对象。

HTTP响应报文解剖

HTTP的响应报文也由三部分组成(响应行+响应头+响应体):


以下是一个实际的HTTP响应报文:


①报文协议及版本;

②状态码及状态描述;

③响应报文头,也是由多个属性组成;

④响应报文体,即我们真正要的“干货”。

响应状态码

和请求报文相比,响应报文多了一个“响应状态码”,它以“清晰明确”的语言告诉客户端本次请求的处理结果。HTTP的响应状态码由5段组成:

1xx:消息,一般是告诉客户端,请求已经收到了,正在处理,别急。

2xx:处理成功,一般表示:请求收悉、我明白你要的、请求已受理、已经处理完成等信息。

3xx:重定向到其它地方。它让客户端再发起一个请求以完成整个处理。

4xx:处理发生错误,责任在客户端,如客户端的请求一个不存在的资源,客户端未被授权,禁止访问等。

5xx:处理发生错误,责任在服务端,如服务端抛出异常,路由出错,HTTP版本不支持等。

以下是几个常见的状态码:

200:OK。你最希望看到的,即处理成功!

303:See Other。我把你redirect到其它的页面,目标的URL通过响应报文头的Location告诉你。

304:Not Modified。告诉客户端,你请求的这个资源至你上次取得后,并没有更改,你直接用你本地的缓存。

404:Not Found。你最不希望看到的,即找不到页面。如你在google上找到一个页面,点击这个链接返回404,表示这个页面已经被网站删除了,google那边的记录只是美好的回忆。

500:Internal Server Error。看到这个错误,你就应该查查服务端的日志了,肯定抛出了一堆异常。

其它的状态码参见:http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

有些响应码,Web应用服务器会自动给生成。你可以通过HttpServletResponse的API设置状态码:

//设置状态码,状态码在HttpServletResponse中通过一系列的常量预定义了,如SC_ACCEPTED,SC_OK
void    setStatus(int sc)

常见的HTTP响应报文头属性

Cache-Control:响应输出到客户端后,服务端通过该报文头属告诉客户端如何控制响应内容的缓存。下面的设置让客户端对响应内容缓存3600秒,也即在3600秒内,如果客户再次访问该资源,直接从客户端的缓存中返回内容给客户,不要再从服务端获取(这个功能是靠客户端实现的,服务端只是通过这个属性提示客户端“应该这么做”。做不做还是决定于客户端,如果是自己宣称支持HTTP的客户端,则就应该这样实现)。

Cache-Control: max-age=3600

ETag:一个代表响应服务端资源(如页面)版本的报文头属性,如果某个服务端资源发生变化了,这个ETag就会相应发生变化。它是Cache-Control的有益补充,可以让客户端“更智能”地处理什么时候要从服务端取资源,什么时候可以直接从缓存中返回响应。关于ETag的说明,你可以参见:http://en.wikipedia.org/wiki/HTTP_ETag。

Spring 3.0还专门为此提供了一个org.springframework.web.filter.ShallowEtagHeaderFilter(实现原理很简单,对JSP输出的内容MD5,这样内容有变化ETag就相应变化了),用于生成响应的ETag,因为这东东确实可以帮助减少请求和响应的交互。下面是一个ETag:

ETag: "737060cd8c284d8af7ad3082f209582d"

Location:我们在JSP中让页面Redirect到一个某个A页面中,其实是让客户端再发一个请求到A页面,这个需要Redirect到的A页面的URL,其实就是通过响应报文头的Location属性告知客户端的,如下的报文头属性,将使客户端redirect到iteye的首页中:

Location: http://www.iteye.com

Set-Cookie:服务端可以设置客户端的Cookie,其原理就是通过这个响应报文头属性实现的:

Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1

更多其它的HTTP响应头报文,参见:http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

如何写HTTP请求报文头

在服务端可以通过HttpServletResponse的API写响应报文头的属性:

//添加一个响应报文头属性
void    setHeader(String name, String value)

像Cookie、Location这些响应都是有福之人,HttpServletResponse为它们都提供了VIP版的API:

//添加Cookie报文头属性
void addCookie(Cookie cookie)
//不但会设置Location的响应报文头,还会生成303的状态码呢,两者天仙配呢
void    sendRedirect(String location)

session和cookie的最深刻理解

对SESSION的争论好像一直没有停止过,不过能理解SESSION的人应该占90以上。有一些人赞成用SESSION,有一些人不赞成。有些人应该知道我是做江湖程序的,而江湖程序做看中的就是效率,但这里不谈设计,而从一些比较实际的角度看SESSION。首先要先说SESSION是干什么的,SESSION是可以存储针对与某一个用户的IE以及通过其当前窗口打开的任何窗口具有针对性的用户信息存储机制。为什么要这样说。看下边:

先研究SESSION是如何启动的,当打开IE以后浏览网站后会发出一个指令请求SESSIONID以及对各个类型数据的下载许可。如图片、声音以及FLASH。数据实际传输内容:IE到服务器:

GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*
Accept-Language0: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: www.jh521.com
Connection: Keep-Alive

服务器会返回一个没有被使用的SESSIONID让IE使用,当时IE就对返回SESSIONID做存储并同时返回相关页面的下载数据,如下:服务器到IE。

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Sun, 30 Nov 2003 16:41:51 GMT
Content-Length: 21174..Content-Type: text/html
Set-Cookie: ASPSESSIONIDCACBBBRT=IBOMFONAOJFEEBHBPIENJFFC; path=/
Cache-control: private

然后就是页面HTML代码,此时这个IE程序(不是客户机)的SESSIONID就为IBOMFONAOJFEEBHBPIENJFFC。而当IE在访问这个站点的任何ASP程序的时候,就会把IBOMFONAOJFEEBHBPIENJFFC发送给服务器,服务器就会知道IBOMFONAOJFEEBHBPIENJFFC是表示你,而在服务器上设置

SESSION("name")="name"

完全可以看成是

SESSION("IBOMFONAOJFEEBHBPIENJFFC")("name")="name"

或者

SESSION(SESSIONID)("name")="name"

这样,SESSION就区分开用户了。而当服务器反馈这个ID的时候会看这个ID有没有被使用。如果有在换一个反正不会让你重复,如果想模拟某人的SESSION的ID来进行欺骗是可以的。不过要获取到对方IE传输信号,并且在保证当时这个SESSIONID没有被取消的情况下才可能实施。

不过要是我有那时间直接通过POST信号找他NAME和PASS了。我可不费这个劲,想必一些人明白了了SESSIONID到底是如何工作的。那么就在看看COOKIE,有人说SESSIONID就是COOKIE,按照技术上来讲他们不属于同类。但是属于一种工作模式,用户和服务器传输私有数据,当我设置COOKIE的时候,服务器会反馈给IE一个指令。IE通过这个网络指令生成COOKIE并存放,在特定的时候会取得这个这个信息如在访问这个站点并且COOKID有效的时候。

那么为什么要用COOKIE而不用SESSION呢?在有效时间以及存储方式和传输内容方面来说。COOKIE可设置并在本地保留并明码信息,SESSION在IE不关闭并服务器不超时并只有SESSIONID。如果想让用户下次登入网站不需要输入用户名或者密码的时候就只能用COOKIE,因为他可以保留相当长的时间(在COOKIE记录被删除或者失效日期之前)。而SESSION就不可以,他不会保留太长时间,而且IE在关闭后就自动清除了SESSIONID记录,在下次登入的时候会请求新的SESSIONID。

cookie 和session 的区别:

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗。考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用COOKIE

4、单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。

5、个人建议将登陆信息等重要信息存放为SESSION,其他信息如果需要保留,可以放在COOKIE中

默认cookies失效时间是直到关闭浏览器,cookies失效,也可以指定cookies时间。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值