关于http几组有用的消息头

来源:互联网 发布:汽车零部件出口数据 编辑:程序博客网 时间:2024/06/05 09:38

http协议有很多有意思并且有用的消息头,这里重点总结一些实用的。比如,我们如何对站点的静态资源做防盗链?如何记录网站的访问来源从而统计各大搜索引擎的流量?再比如,我们自己做的一些简单的页面,需要有账号密码验证,但是我们又不想再为它写一个登录页面,应该怎么办?这些问题都可以通过http协议一些特定的消息头去解决。


Referer


Referer是请求头信息,用于记录访问的来源。比如,从A.html跳转到B.html,或者在A.html里引用了B.png,此时的请求报文里都会带着Referer: A.html这样的请求消息头。
有了这样的信息,我们就可以通过检查Referer值的方式来给B.png这样的资源文件做防盗链;通过记录Referer值来记录网页的访问来源。

BASIC认证相关


BASIC认证(基本认证)是从HTTP/1.0就定义的认证方式。玩过tomcat的人一定都记得它的管理页面在要求输入用户名密码的时候,是弹出了一个窗口,第一次感觉很神奇,怎么做到的。其实使用的就是BASIC认证。这种认证遵循着特定的约定,浏览器在遇到特定的响应码以及响应头的时候,就会弹出窗口让用户输入用户名密码。下面会详细介绍认证机制。因为这种认证不安全,同时也不是很灵活,唯一的好处就是能够为我们省下一个登录页面,所以,通常很少使用,一般都用在那些仅限开发人员使用的管控项目里。另外,像nginx会有这种BASIC认证模块,这样我们连后台的登录逻辑都不用写了,直接裸项目,认证全部交给nginx。



时序一:浏览器第一次在未经过BASIC认证的情况下发送一个请求到服务端。
时序二:服务端判断请求头没有Authorization信息,认证失败,返回401状态码以及WWW-authenticate响应头。
时序三:浏览器在收到这样的响应之后,会遵循http协议,自动弹出输入框,以供用户输入用户名密码。
时序四:用户提交uname和pwd之后,浏览器会用冒号将uname和pwd拼接起来,通过Base64进行编码,前面再拼接上”Basic ”,作为请求头Authorization传递给服务端。
时序五:服务端解码取出uname和pwd,作认证。
时序六:服务端认证成功,把资源响应给浏览器。
时序七:浏览器以后再请求相同域名的资源,都会自动携带上一次被认证成功的请求头Authorization。

BASIC认证虽然采用Base64编码方式,但这不是加密处理。不需要任何附加信息即可对其进行解码。换言之,由于明文解码后就是用户名和密码,在http等非加密通信的线路上进行BASIC认证的过程中,如果被人监听,被盗的可能性极高。
另外,除此之外想再进行一次BASIC认证时,一般的浏览器却无法实现认证注销操作,这也是问题之一。

缓存相关


Last-Modified | If-Modified-Since


这组缓存相关的头信息特别巧妙,它的机制并不是说浏览器直接读本地缓存不用向服务器发送请求。而是通过避免服务端向浏览器频繁输出流的方式来达到提高性能的目的。同时,因为客户端每次都会和服务端产生交互,所以呢,如果服务端的资源有变更,客户端是能够及时获得最新资源的。整个机制下客户端和服务端一直都在交互协商,所以这种缓存又叫协商缓存。



第一次访问xx.html,服务端发现没有If-Modified-Since头信息,响应真实的xx.html内容,同时返回Last-Modified信息头。
第二次访问xx.html,浏览器会自动携带If-Modified-Since,服务端拿着这个值和文件的修改时间作比较,如果值一样,说明文件没有修改,直接返回304,不返回xx.html的内容了,浏览器收到这样的状态码,就会按照约定读本地缓存,从而减少了服务器和客户端之间传送文件内容的时间,提高了性能。
在这个过程中,文件内容有修改,那么服务器在比较两个时间的时候,发现不一样,就会返回真实的文件内容,并且把最新的修改时间作为Last-Modified返回给客户端。浏览器会更新If-Modified-Since,下一次会传递这个最新值给服务端。
任何一个web容器在处理静态资源的时候,都会遵照这种约定,比如tomcat,tomcat处理静态资源的类DefaultServlet就是这么处理的。

Etag | If-None-Match


通过上面一组缓存头信息的学习,我们发现这种协商缓存很不错,既能达到缓存的效果,又能实时获取最新的内容。但是,通过修改时间还是存在一些缺陷的:
Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间;如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存。
Etag很好的弥补了Last-Modified的不足,它是根据文件内容生成一个标签,只有文件内容变化,Etag值才会变,这比Last-Modified更加准确。除此之外,Etag/If-None-Match的机制和Last-Modified/If-Modified-Since完全相同。
同样的,对于这组头信息,各个web容器都要支持。关于Etag的生成算法,不同的容器不同的算法。tomcat的DefaultServlet处理的比较low,它是简单的将文件的修改时间和文件的大小拼接起来作为文件的Etag,我们知道使用修改时间是有缺陷的。

Cache-Control | Expires


上面两组头信息所对应的缓存叫做协商缓存,可以达到缓存效果,但是,你可能比较追求极致,无法接受每次和服务器都有交互,那么,可以考虑Cache-Control/Expires。
这组头信息所对应的缓存又被称作强缓存,因为这次真的是不再和服务器交互协商,完全使用本地缓存,当然了,它和我们熟悉的很多缓存领域一样,可以设置过期时间。
Expires和Cache-Control都是响应头。
Expires是http1.0就已经定义的,类似于:Expires:Fri, 08 Sep 2017 17:49:18 GMT。服务器端通过这个值来告诉浏览器缓存截止的有效期,是个时间点,如果我们给一个静态资源设置的有效期是3天,那么这个值就是客户端真正访问服务端资源的时间点的后三天,在这时间之前,浏览器使用本地缓存,过了这个时间,浏览器再次向服务端请求。
Cache-Control是http1.1定义的,其实它的设置特别细致,值有很多,像Public、no-cache、no-store什么的,我们重点讲关于过期时间。关于过期时间,它的设置类似于:Cache-Control:max-age=259200。如果我们给一个静态资源设置的有效期是3天,那么这个值就是3天的秒数。

同样,对于这组头信息,各个web容器要支持。Tomcat关于静态资源强缓存的配置是通过在项目web.xml中对org.apache.catalina.filters.ExpiresFilter的配置。默认不强缓存,如果要对静态资源做缓存时间为10天的配置,可以在项目web.xml增加如下配置:
<filter><filter-name>ExpiresFilter</filter-name><filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class><init-param><param-name>ExpiresByType image</param-name><param-value>access plus 10 days</param-value></init-param><init-param><param-name>ExpiresByType text/css</param-name><param-value>access plus 10 days</param-value></init-param><init-param><param-name>ExpiresByType application/javascript</param-name><param-value>access plus 10 days</param-value></init-param><init-param><param-name>ExpiresByType text/html</param-name><param-value>access plus 10 days</param-value></init-param></filter><filter-mapping><filter-name>ExpiresFilter</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher></filter-mapping>

范围请求


还有一组特别有用的消息头,让我们请求资源的时候,可以指定字节范围,比如通过http下载文件的时候,可以通过Range指定只下载5000-10000字节的内容,我们称之为范围请求。范围请求的场景多用于下载的多线程断点续传。关于范围请求以及多线程断点续传,可以阅读之前的一篇文章,多线程断点下载,里面有很详细的介绍。

原创粉丝点击