[http] كيفية التحكم في التخزين المؤقت لصفحة الويب ، عبر جميع المتصفحات؟



Answers

(مهلا ، الجميع: من فضلك لا مجرد نسخ ولصق جميع العناوين التي يمكنك العثور عليها)

أولاً ، لا يُعد سجل زر "السابق" ذاكرة تخزين مؤقت :

لا ينطبق نموذج الحداثة (القسم 4.2) بالضرورة على آليات التاريخ. بمعنى ، يمكن آلية سجل عرض تمثيل سابق حتى إذا انتهت صلاحيتها.

في مواصفات HTTP القديمة ، كانت الصياغة أكثر قوة ، حيث تخبر المتصفحات صراحةً بتجاهل توجيهات ذاكرة التخزين المؤقت لمحفوظات زر الرجوع.

من المفترض العودة للعودة في الوقت المناسب (إلى الوقت الذي تم فيه تسجيل دخول المستخدم). لا يتنقل إلى عنوان URL مفتوح مسبقًا.

ومع ذلك ، من الناحية العملية ، يمكن أن تؤثر ذاكرة التخزين المؤقت على زر الرجوع ، في ظروف محددة للغاية:

  • يجب تسليم الصفحة عبر HTTPS ، وإلا لن يكون خرق ذاكرة التخزين المؤقت موثوقًا. بالإضافة إلى ذلك ، إذا كنت لا تستخدم HTTPS ، فستكون صفحتك عرضة لسرقة الدخول بعدة طرق أخرى.
  • يجب أن ترسل Cache-Control: no-store, must-revalidate (بعض المتصفحات تلاحظ no-store ، ويلاحظ البعض أنه must-revalidate )

لست بحاجة إلى أي من:

  • <meta> مع رؤوس ذاكرة التخزين المؤقت - لا تعمل على الإطلاق. عديم الجدوى إطلاقا.
  • post-check / post-check pre-check - هو التوجيه IE- فقط الذي ينطبق فقط على الموارد cachable .
  • إرسال نفس الرأس مرتين أو في عشرات الأجزاء. تعمل بعض مقتطفات PHP في الواقع على استبدال الرؤوس السابقة ، مما يؤدي إلى إرسال آخر رأس فقط.

إذا كنت تريد ، فيمكنك إضافة:

  • no-cache أو max-age=0 ، مما سيجعل المورد (URL) "قديمًا" ويتطلب من المتصفحات التحقق من الخادم إذا كان هناك إصدار أحدث ( no-store يعني no-store بالفعل هذا أقوى).
  • Expires بتاريخ سابق لعملاء HTTP / 1.0 (على الرغم من أن عملاء HTTP / 1.0-only الحقيقيين غير موجودون تمامًا في هذه الأيام).

مكافأة: التخزين المؤقت الجديد لـ HTTP RFC .

Question

أظهرت تحرياتنا أنه ليس جميع المتصفحات تحترم توجيهات ذاكرة التخزين المؤقت http بطريقة موحدة.

لأسباب تتعلق بالأمان ، لا نريد أن يتم تخزين صفحات معينة في التطبيق الخاص بنا في ذاكرة التخزين المؤقت ، على الإطلاق ، بواسطة متصفح الويب. يجب أن يعمل هذا على الأقل مع المتصفحات التالية:

  • إنترنت إكسبلورر 6+
  • Firefox 1.5+
  • سفاري 3+
  • أوبرا 9+
  • كروم

جاء متطلبنا من اختبار أمني. بعد تسجيل الخروج من موقعنا على الويب ، يمكنك الضغط على زر الرجوع وعرض الصفحات المخبأة.




لقد حققت أفضل النتائج وأكثرها تناسقًا عبر جميع المتصفحات من خلال تعيين Pragma: no-cache




انظر هذا الرابط إلى دراسة حالة عن التخزين المؤقت:

http://securityevaluators.com/knowledge/case_studies/caching/

الملخص ، وفقًا للمقال ، لا Cache-Control: no-storeيعمل إلا على Chrome و Firefox و IE. يقبل IE عناصر التحكم الأخرى ، ولكن لا يفعل Chrome و Firefox. الرابط هو قراءة جيدة كاملة مع تاريخ التخزين المؤقت وتوثيق دليل على المفهوم.




I just want to point out that if someone wants to prevent caching ONLY dynamic content, adding those additional headers should be made programmatically.

I edited configuration file of my project to append no-cache headers, but that also disabled caching static content, which isn't usually desirable. Modifying response headers in code assures that images and style files will be cached.

This is quite obvious, yet still worth mentioning.

And another caution. Be careful using ClearHeaders method from HttpResponse class. It may give you some bruises if you use it recklessly. Like it gave me.

After redirecting on ActionFilterAttribute event the consequences of clearing all headers are losing all session data and data in TempData storage. It's safer to redirect from an Action or don't clear headers when redirection is taking place.

On second thought I discourage all to use ClearHeaders method. It's better to remove headers separately. And to set Cache-Control header properly I'm using this code:

filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");



In addition to the headers consider serving your page via https . Many browsers will not cache https by default.




بعد قليل من البحث توصلنا إلى قائمة العناوين التالية التي يبدو أنها تغطي معظم المتصفحات:

في ASP.NET أضفناها باستخدام المقتطف التالي:

Response.ClearHeaders(); 
Response.AppendHeader("Cache-Control", "no-cache"); //HTTP 1.1
Response.AppendHeader("Cache-Control", "private"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "no-store"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "must-revalidate"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "max-stale=0"); // HTTP 1.1 
Response.AppendHeader("Cache-Control", "post-check=0"); // HTTP 1.1 
Response.AppendHeader("Cache-Control", "pre-check=0"); // HTTP 1.1 
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0 
Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); // HTTP 1.0 

تم العثور عليه من: http://forums.asp.net/t/1013531.aspx




Also, just for good measure, make sure you reset the ExpiresDefault in your .htaccess file if you're using that to enable caching.

ExpiresDefault "access plus 0 seconds"

Afterwards, you can use ExpiresByType to set specific values for the files you want to cache:

ExpiresByType image/x-icon "access plus 3 month"

This may also come in handy if your dynamic files eg php, etc. are being cached by the browser, and you can't figure out why. Check ExpiresDefault .




إخلاء المسؤولية: أقترح بقوة قراءة الإجابة @ BalusC. بعد قراءة البرنامج التعليمي للتخزين المؤقت التالي: http://www.mnot.net/cache_docs/ (أوصي بقراءته أيضًا) ، أعتقد أنه صحيح. ومع ذلك ، ولأسباب تاريخية (ولأنني قمت باختبارها بنفسي) ، فسوف أضمِّن إجابتي الأصلية أدناه:

جربت الإجابة "المقبولة" لـ PHP ، والتي لم تنجح بالنسبة لي. ثم أجريت بحثًا صغيرًا ، ووجدت متغيرًا بسيطًا ، واختبرته ، وعمل. ها هو:

header('Cache-Control: no-store, private, no-cache, must-revalidate');     // HTTP/1.1
header('Cache-Control: pre-check=0, post-check=0, max-age=0, max-stale = 0', false);  // HTTP/1.1
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');                  // Date in the past  
header('Expires: 0', false); 
header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
header ('Pragma: no-cache');

التي يجب أن تعمل. كانت المشكلة أنه عند تعيين نفس الجزء من الرأس مرتين ، إذا لم يتم إرسال false كوسيطة ثانية إلى الدالة الرأس ، فستقوم ببساطة وظيفة الرأس بالكتابة فوق استدعاء header() السابق. لذا ، عند إعداد Cache-Control ، على سبيل المثال إذا لم يرغب أحد في وضع جميع الوسيطات في استدعاء الدالة header() ، فعليه أن يفعل شيئًا كالتالي:

header('Cache-Control: this');
header('Cache-Control: and, this', false);

انظر المزيد من الوثائق كاملة here .




لقد وجدت أن جميع الإجابات على هذه الصفحة لا تزال تواجه مشكلات. على وجه الخصوص ، لاحظت أن أيا منهم لن يوقف IE8 من استخدام نسخة مخبأة من الصفحة عند الوصول إليها عن طريق الضغط على زر الرجوع.

بعد الكثير من الأبحاث والاختبارات ، اكتشفت أن العنوانين الرئيسيين اللذين كنت أحتاجهما حقًا هما:

Cache-Control: no-store
تختلف: *

للحصول على شرح لرؤيتها Vary ، اطلع على http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

على IE6-8 و FF1.5-3.5 و Chrome 2-3 و Safari 4 و Opera 9-10 ، تسببت هذه الرؤوس في طلب الصفحة من الخادم عند النقر على رابط إلى الصفحة ، أو وضع عنوان URL مباشرة في شريط العنوان. يغطي هذا حوالي 99% من جميع المتصفحات المستخدمة اعتبارًا من Jan 10.

على IE6 ، و Opera 9-10 ، لا يزال الضغط على زر العودة يسبب تحميل النسخة المخبأة. على جميع المتصفحات الأخرى التي اختبرتها ، قاموا بجلب نسخة جديدة من الخادم. حتى الآن ، لم أجد أي مجموعة من الرؤوس التي تتسبب في عدم عرض تلك المستعرضات للنسخ المخزنة مؤقتًا للصفحات عند النقر على زر الرجوع.

تحديث: بعد كتابة هذه الإجابة ، أدركت أن خادم الويب الخاص بنا يعرّف نفسه على أنه خادم HTTP 1.0. العناوين التي سردتها هي العناوين الصحيحة لاستجابات من خادم HTTP 1.0 حتى لا يتم تخزينها مؤقتًا بواسطة المتصفحات. للحصول على خادم HTTP 1.1 ، انظر إلى answer BalusC.




لا تمنع الرؤوس في الإجابة المقدمة من BalusC Safari 5 (وربما الإصدارات القديمة أيضًا) من عرض المحتوى من ذاكرة التخزين المؤقت للمتصفح عند استخدام زر الرجوع في المتصفح. طريقة لمنع هذا هي إضافة سمة معالج حدث onunload فارغ إلى علامة النص الأساسي:

<body onunload=""> 

يبدو أن هذا الاختراق يكسر ذاكرة التخزين المؤقت في Safari: هل هناك حدث onload للمتصفح المتقاطع عند النقر على زر الرجوع؟




في حالتي إصلاح المشكلة في الكروم مع هذا

<form id="form1" runat="server" autocomplete="off">

حيث أحتاج إلى مسح محتوى بيانات النموذج السابق عندما يقوم المستخدمون بالنقر فوق الزر مرة أخرى لأسباب أمنية




يقول RFC لـ HTTP 1.1 إن الأسلوب المناسب هو إضافة رأس HTTP لـ:

Cache-Control: no-cache

قد تتجاهل المتصفحات القديمة هذا إذا لم تكن متوافقة مع HTTP 1.1 بشكل صحيح. بالنسبة إلى هؤلاء ، يمكنك تجربة العنوان:

Pragma: no-cache

هذا من المفترض أيضًا أن يعمل للمتصفحات HTTP 1.1.




تحتوي وثائق PHP الخاصة بوظيفة الرأس على مثال كامل (ساهم به طرف ثالث):

    header('Pragma: public');
    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");                  // Date in the past   
    header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
    header('Cache-Control: no-store, no-cache, must-revalidate');     // HTTP/1.1
    header('Cache-Control: pre-check=0, post-check=0, max-age=0', false);    // HTTP/1.1
    header ("Pragma: no-cache");
    header("Expires: 0", false);



Links