ホームページ > バックエンド開発 > PHPチュートリアル > http プロトコル、Cookie とセッション メカニズム、ブラウザ キャッシュの簡単な分析

http プロトコル、Cookie とセッション メカニズム、ブラウザ キャッシュの簡単な分析

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
リリース: 2016-06-20 13:03:00
オリジナル
1022 人が閲覧しました

ここ数日間、私はヘッダー、Cookie、セッション、キャッシュ、および http プロトコルのその他の関連知識を検討し、いくつかの新しい知識点を発見しました。

この記事では、これらの内容を理解するために PHP を組み合わせることに焦点を当てています。つまり、実践的な部分により重点を置いています。

1. http ヘッダー

NO1: Web アプリケーションの場合、ユーザー グループはクライアント (さまざまなブラウザー) 上の任意の接続をクリックしてサーバーに http リクエストを送信します。このプロセスでは接続を確立するために 3 回のハンドシェイクが必ず必要となり、サーバーはデータを返すことで応答します。 。

すべてのリクエストにはヘッダーとエンティティ部分があります。まず、作成者が QQ スペースで監視するヘッダーを見てみましょう。QQ スペースの理由は、そのヘッダーの内容が比較的完全であるためです。

    Request Headers: 
       
    GET http://user.qzone.qq.com/445235728 HTTP/1.1 
       
    Host: user.qzone.qq.com 
       
    Connection: keep-alive 
       
    Cache-Control: max-age=0 
       
    User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11 
       
    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
       
    Referer: http://qzone.qq.com/ 
       
    Accept-Encoding:gzip,deflate,sdch 
       
    Accept-Language: zh-CN,zh;q=0.8 
       
    Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3 
       
    Cookie:o_cookie=445235728;(省略很多……) 
       
    If-Modified-Since: Wed, 13 Jun 2012 01:32:19 GMT 
       
    ----------------- 
       
    Response Headers: 
       
    HTTP/1.1 200 OK 
       
    Connection:close 
       
    Server: QZHTTP-2.34.0 
       
    Date: Wed, 13 Jun 2012 02:59:31 GMT 
       
    Content-Encoding: gzip 
       
    Set-Cookie:login_time=61F0EEA02D704B1DBCF25166A74941B24F4BE24B205C466F;PATH=/; DOMAIN=qzone.qq.com 
       
    Set-Cookie:Loading=Yes;expires=Wed,13-Jun-201216:00:00GMT;PATH=/;DOMAIN=qzone.qq.com X-UA-Compatible: IE=Edge Last-Modified: Wed, 13 Jun 2012 02:59:31 GMT 
       
    Cache-Control: max-age=0, no-transform 
       
    Content-Type: text/html;charset=utf-8 
       
    Transfer-Encoding: chunked
ログイン後にコピー

1. クライアント要求ヘッダーには、要求行といくつかのヘッダー フィールドが含まれます。

リクエスト行: リクエスト メソッドの URL (Uniform Resource Identifier) プロトコル バージョン -------3 つをスペースで区切って、最後に新しい行 (rn) を入力します。例: GET http://user.qzone。 qq .com/445235728 HTTP/1.1

さまざまなヘッダー フィールド: これらのヘッダー フィールドは、キーワードとキー値のペアで構成され、最後に改行とキャリッジ リターン (rn) で終わります。これらのヘッダー フィールドは、サーバーに応答方法と独自のフィールドの一部を指示します。情報。

2. サーバーの応答

ステータス行: プロトコルのバージョン、応答ステータス、ステータスの説明 --これら 3 つはスペースで区切られ、最後に改行とキャリッジ リターン (rn) が続きます。例: HTTP/1.1 200 OK

さまざまなヘッダー フィールド: これらのヘッダー フィールドには、キーワードとキー値のペアの組み合わせもあり、最後に改行とキャリッジ リターン (rn) で終わります。これらのヘッダー フィールドは、クライアントに応答方法と独自の情報の一部を伝えます。

NO2

ここでは各ヘッダー フィールドの概念と機能については説明しません。詳しく知りたい場合は、http://www.phpben.com/?post=34 を参照してください。重要だと思われるいくつかのテストは、一部の Web サイトで使用されています。データとリクエストの戻りヘッダー フィールドの php コード実装

テスト時期: 2012.6.14 以前

テスト対象: csdn、cnbeta、cnblos、Tencent (QQ Zone、Friends.com、News Network)、Sina (Weibo、ホームページ)、Renren、Baidu、Taobao、Youku、Tudou およびその他の Web サイト

(1) 接続ヘッダー フィールド: このヘッダー フィールドは http/1.1 でのみ使用できます。デフォルト値は、長い接続を示すキープアライブ値です。この方法では、接続のたびにサーバーに接続する必要はありません。画像、CSS ファイル、JS ファイルなどのリソースが要求される場合は、3 回のハンドシェイク接続を実行します。これにより、HTTP ステートレス性の欠点がある程度補われ、サーバーへの接続時間が短縮されます。

テスト Web サイトの Connection ヘッダー フィールドを見ると、Tencent QQ Zone、Tencent News Network、Sina Home Page、Weibo、Youku、Tudou の接続: これらを除き、その他は接続: keep-alive であることがわかりました。

なぜ?

1. connection: keep-alive を通常に使用するための前提条件は、本文の長さをクライアントに伝えるために content-length ヘッダー フィールドを提供することです。テキストの長さの計算は問題ですが、マルチコンテンツ サーバーやクラスター サーバーではこれが容易ではありません。 Tencent、Sina、Youku ではこれらを計算するのは難しく、エンジニアには非公開になっています (デフォルトは公開されています)。

2. 古いサーバーはサポートしていません。Tencent や Sina などの古いサーバーでは、サーバー クラスターが非常に大きいため、互換性の問題により、一部の古いサーバーは直接閉じられます。

追伸: これら 2 つの理由は検証されていません。 ^-^

php ヘッダーを使用する(“Connection:keep-alive”);

(2) Content-Encoding ヘッダーフィールド

Content-Encoding ドキュメントのエンコード (Encode) メソッド。

上記の Web サイトは cnbeta に gzip 圧縮を使用していませんが、Youku は deflate を使用しており、残りは同じです。これは、PHPer が圧縮 gzip 送信テクノロジを習得する必要があるという重要なメッセージも明らかにしています。

Php は mod_gzip モジュールを通じて実装できます。コード: ob_start("ob_gzhandler");

(3) Server ヘッダー フィールドは、サーバーの重要なセキュリティ情報を公開します。

CSDN: サーバー:nginx/0.7.68 ------------ バージョンが公開されています

Tencent QQ Space: サーバー: QZHTTP-2.34.0--------TX 友人によると、これは社内で開発されたサーバーであり、十分安全であることが明らかになりました

新浪微博: サーバー:apache -------------これはリークされたバージョンではありません

Ifeng.com: サーバー: nginx/0.8.53

レンレン: サーバー:nginx/1.2.0

淘宝: Tengine --------これは、淘宝網の内部技術チームによって開発された、Nginx に基づいた Web サーバーです

cnblogs ブログ パーク: サーバー:Microsoft-IIS/7.5

Tencent Friends Network: Tencent/PWS --------Tencent 内部開発

Tencent News Network: サーバー:squid/3.1.18

Youku.com: サーバー: fswww1-----------内部的なものかどうかはわかりませんが、少なくともどこから来たのかはわかりません^_^

Tudou: Tengine/1.2.3

Baidu: サーバー: BWS/1.0 ----------Baidu が社内で開発したサーバーである必要があります

サーバーヘッダーフィールドはサーバーに返される情報であることは明らかですが、この問題に直面して、大企業は独自の機能に基づいて独自の社内サーバーを開発します。

(4) X-Powered-By ヘッダー フィールドは変更可能であり、セキュリティに基づいて変更できます

X-Powered-By ヘッダー フィールドは、バックグラウンド プログラムが実行される言語とバージョンを反映します。これは同じヘッダー関数で変更できます

header("X-Powered-By:acb");

(5) Cache-control、expires、last-modified等重要头域

Cache-control:指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。

Php代码实现:header("cache-control: abc");abc是上述指令值一个或多个,多个用’,’分开

Expires:告诉浏览器指明应该在什么时候认为文档已经过期,从而不再缓存它。代码实现:header("Expires:". date('D, d M Y H:i:s \G\M\T', time()+10));--------这个是把时间截转化成格林时区字符串给expires头域,这个显示时间会比中国北京时间少8个小时,东8区的实现:header("Expires:". date('r', time()+10))

last-modified:这个是服务器返回给浏览器,浏览器下次请求则把该值赋给if-modified-since头域传给服务器,服务器就可以根据此值判断是否有改变,有则继续运行下去,否者返回304 not modified。Php设置expires头域一样。

代码:

    if(isset($_SERVER[&#39;HTTP_IF_MODIFIED_SINCE&#39;]) && (time()-strtotime($_SERVER[&#39;HTTP_IF_MODIFIED_SINCE&#39;]) < 10)) { 
      header("HTTP/1.1 304 Not Modified"); 
         exit; 
       } 
    header("Last-Modified: " . date(&#39;D, d M Y H:i:s \G\M\T&#39;, time()) );或者header("Last-Modified: " . date(&#39;r&#39;, time()) ); 
ログイン後にコピー

前者是格林时间格式,后者是中国时间。需要注意的就是 php.ini 的时区 prc 则用后则,否者前者。笔者曾经试过在时区是 prc 的情况下用了前者,导致 time()-strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) <0 永远成立,因为是负值。

注意:当请求页面有session_start()的时候,则不管是否有expires、cache-control、last-modified设置,则返回给客户端Cache-Control头域为Cache-Control:no-store, no-cache, must-revalidate Expires头域 Expires:Thu, 19 Nov 1981 08:52:00 GMT。这个问题烦了笔者2天,都以为php.ini 或是apache的问题。最后竟然是session_start()的问题。

二、 浏览器缓存动态

前面介绍了http headers几个告诉浏览器如何处理缓存。但不同浏览器处理各种头域的方式不同,以下就是笔者。

Ps:各个浏览器监听http headers的方法可以查看:http://www.phpben.com/?post=76

(1) header(“cache-control: no-store”)

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

同上

同上

同上

同上

(2) header(“cache-control: no-cache”)

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

同上

From cache

From cache

同上

(3) header(“cache-control:bublic”)

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

from cache

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(4) header("cache-control:private"); header("cache-control: must-revalidate ")

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

除第一次外都是from cache

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(5) header("cache-control:max-age=num");num是秒数

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

秒数

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(6)

 header("Expires:". date(&#39;D, d M Y H:i:s \G\M\T&#39;, time()+num)); num是秒数

ログイン後にコピー

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

秒数

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(7)

  if(isset($_SERVER[&#39;HTTP_IF_MODIFIED_SINCE&#39;]) && (time()-strtotime($_SERVER[&#39;HTTP_IF_MODIFIED_SINCE&#39;]) < num)) {

  header("HTTP/1.1 304 Not Modified");

     exit;

   } header("Last-Modified: " . date(&#39;D, d M Y H:i:s \G\M\T&#39;, time()) );
ログイン後にコピー

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

秒数

秒数

秒数

重发请求,返回200状态

地址栏回车

from cache

秒数

秒数

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

结论:

1、 刷新对于任何浏览器且不管是什么cache-control,都会重新请求,一般返回是200,除非Last-Modified设置

2、 后退键除非no-cache; no-store外都是使用缓存

3、 Cache-control:no-store 在浏览器中任何操作都重新提交请求,包括后退

4、 遨游3的缓存很差

5、 IE9 的缓存很强,所以用ie9调试的时候尽可能点刷新而不是在地址栏回车

鉴于这种情况,对于不同的应用(有些要缓存,有些经常更新)对于不同的国家各种浏览器份额,而哪种缓存方式。中国IE比较多,加上360浏览器的加入(用IE内核),那就要主要参照IE浏览器。

但笔者还是比较喜欢header("Last-Modified: " . date('D, d M Y H:i:s \G\M\T', time()) );这种方式。结合起来connection:keep-alive能让缓存技术更成熟。

注意:

1、 也许你会问,用Cache-control:no-store或Cache-control:no-store,但调试页面还是没原来的缓存。然后清除浏览器缓存关掉重启浏览器, 缓存还在。这是因为你的web应用用了文件缓存如ecshop常出现这种情况,这种情况就要进web应用后台删除文件缓存。

2、 调试的时候尽可能不要在地址栏回车,特别是IE,google还好一点,但是要知道这次的测试只是各个浏览器中的一个版本,所以调试的时候尽可能点刷新按钮。

3、 但在cache-control:max-age=num 和expires 一起使用的时候,前者级别比较高,浏览器会忽略expires的设置。(上面没给出测试内容)

三、 Session和cookies

Session 、cookies是程序员永远讨论的话题之一。

1、 简单说一下cookies、session

(1) Cookies是保存在客户端的小段文本,随客户端点每一个请求发送该url下的所有cookies到服务器端。比如在谷歌浏览器下,打开ww.abc.com下的两个文件,a.php包含cookies1和cookies2,b.php包含了cookies3和cookies4,那么在a.php或b.php 点任意一个连接(当然是ww.abc.com服务器上的),浏览器就会把cookies1~4这4个cookies发送给服务器。但是如果在IE9有打开一个包含cookies5的c.php,哪门在google浏览器点击连接是不会发送cookies5的。

(2) Session则保存服务器段,通过唯一的值sessionID来区别每一个用户。SessionID随每个连接请求发送到服务器,服务器根据sessionID来识别客户端,再通过session 的key获取session值。SessionID传回服务器的实现方式可以通过cookies和url回写来实现。

注意:

1、 同一个浏览器打开同一个文件,如a.php ,或同时有设置session的两个文件a.php、b.php sessionID则只有一个。(时间上不能是打开a.php 关闭浏览器再打开b.php)

2、 不同浏览器在同一时间打开同意文件的sessionID也不一样

3、 sessionID是服务器生成的不规则唯一字符串,如:

PHPSESSID=05dbfffd3453b7be02898fdca4fcd82b;------ PHPSESSID可以通过php.ini中session.name来改变,所以笔者在监听一些大型网站的时候查不出PHPSESSID,这是一个安全因素。

(3) cookies、session在php中的主要相关参数

(1) session.save_handler = ”files”

默认以文件方式存取session数据,如果想要使用自定义的处理器来存取session数据,比如数据库,用”user”。

(2) session.use_cookies = 1 前面说到sessionID用cookies来实现,这里就是,1表示用cookies

(3) session.use_trans_sid = 0 上面是用cookies来实现sessionID,这里值若是1则使用url回写方式,级别比session.use_cookies高

(4) session.use_only_cookies = 0 值为1则sessionID只可以用cookies实现,级别比前两个高

(5) session.cache_expire =180 session 缓存过期的秒数

(6) session.gc_maxlifetime = 1440

设定保存的session文件生存期,超过此参数设定秒数后,保存的数据将被视为’垃圾’并由垃圾回收程序清理。判断标准是最后访问数据的时间(对于FAT文件系统是最后刷新数据的时间)。如果多个脚本共享同一个session.save_path目录但session.gc_maxlifetime不同,将以所有session.gc_maxlifetime指令中的最小值为准。

(4) 图说cookie 、ssession

php代码如下

session_start(); 
   
$_SESSION[&#39;favcolor&#39;] = &#39;green&#39;; 
   
$_SESSION[&#39;animal&#39;]   = &#39;cat&#39;; 
   
$_SESSION[&#39;time&#39;]     = time(); 
   
setcookie("cookie1","www.scutephp.com",time()+3600*10); 
   
setcookie("cookie2","www.scutephp.com",time()+3600*10);
ログイン後にコピー

结论:

1、 第一次请求是没用cookies的,而第二次有PHPSESSID和两个cookies是因为服务器第一请求返回这个三个cookies。

2、第二次请求比第一次多返回PHPSESSID这个cookies,在第二次则没有了,直到session过期后重新设置。

2、 ;浏览器关掉cookies,session是否可以正常运行?

前面提及sessionID的时候有两种方式。

(1) cookies 方式,在session.use_trans_sid=0 and session.use_cookies = 1的情况下使用。这种方法是每次浏览器端点每个请求,都把sessionID发送到服务器。

(2) url回写,session.use_only_cookies = 0 and session.use_trans_sid=1的情况下,服务器会忽略session.use_trans_sid,在浏览器发hhtp请求后,服务器会在返回页面内容中每个连接后面加上PHPSESSID=05dbfffd3453b7be02898fdca4fcd82b (在php.ini没改session.name,默认是PHPSESSID),这样就算客户端的浏览器禁止了cookies,一样能实现session功能。

这里来个测试:

在1.php文件代码:

    echo &#39;Welcome to page #1<br/>&#39;; 
       
    session_start(); 
       
    $_SESSION[&#39;favcolor&#39;] = &#39;green&#39;; 
       
    $_SESSION[&#39;animal&#39;]   = &#39;cat&#39;; 
       
    $_SESSION[&#39;time&#39;]     = time(); 
       
    // Works if session cookie was accepted 
       
    echo &#39;<br /><a href="2.php">page 1 (这个href中没SID参数)</a><br/>&#39;; 
    // Or maybe pass along the session id, if needed 
       
    echo &#39;<br /><a href="2.php?&#39; . SID . &#39;">page 2 (这个href中有SID参数)</a><br/>&#39;; 
ログイン後にコピー

在 2.php 文件代码:

session_start(); 
echo &#39;Welcome to page #2<br />&#39;; 
   
echo $_SESSION[&#39;favcolor&#39;],&#39;<br/>&#39;; // green 
   
echo $_SESSION[&#39;animal&#39;],&#39;<br/>&#39;;   // cat 
   
echo date(&#39;Y m d H:i:s&#39;, $_SESSION[&#39;time&#39;]),&#39;<br/>&#39;; 
   
// You may want to use SID here, like we did in page1.php 
   
echo &#39;<br /><a href="1.php">return page 1</a>&#39;; 
ログイン後にコピー

情景1:没禁用浏览器的cookies(用cookies实现session),则在2.php能正常输出

情景2:禁用用浏览器的cookies且在php.ini开启session.use_trans_sid=1,通过1.php第一连接过去显示不了session的值,但第二个连接则正常显示。(说明url回写正常运行)


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート