เราควบคุมการแคชหน้าเว็บในทุกเบราว์เซอร์ได้อย่างไร


1552

การตรวจสอบของเราแสดงให้เราเห็นว่าไม่ใช่ทุกเบราว์เซอร์ที่เกี่ยวข้องกับคำสั่งแคช HTTP อย่างสม่ำเสมอ

เพื่อความปลอดภัยเราไม่ต้องการบางหน้าในโปรแกรมของเราจะถูกเก็บไว้ที่เคยโดยเว็บเบราว์เซอร์ สิ่งนี้จะใช้ได้กับเบราว์เซอร์ต่อไปนี้อย่างน้อย:

  • Internet Explorer 6+
  • Firefox 1.5+
  • Safari 3+
  • Opera 9+
  • โครเมียม

ความต้องการของเรามาจากการทดสอบความปลอดภัย หลังจากออกจากเว็บไซต์ของเราคุณสามารถกดปุ่มย้อนกลับและดูหน้าแคช


สำหรับ ipad Safari เพียง [สิ่งนี้] [1] ช่วยไหม [1]: stackoverflow.com/questions/24524248/…
Bakhshi

วิธีที่ง่ายที่สุดคือใช้: max-age = 10 สิ่งนี้ไม่สมบูรณ์เพราะหน้าจะถูกแคชเป็นเวลา 10 วินาที แต่มันคือ "สปาเก็ตตี้หัว" ทางออกที่น้อยที่สุด นอกจากนี้บางครั้งยังเพิ่มประสิทธิภาพการทำงานอย่างมากในเว็บไซต์แบบไดนามิกที่ใช้พร็อกซีย้อนกลับ (สคริปต์ php ที่ช้าของคุณจะถูกเรียกหนึ่งครั้งทุก ๆ 10 วินาทีและจากนั้นจะถูกแคชโดย reverse proxy หนึ่งครั้งต่อ 10 วินาทีนั้นดีกว่าหนึ่งครั้งต่อผู้เยี่ยมชม)
สวัสดีชาวโลก


3
ขอบคุณสำหรับคำถามที่ดีมาก อยากรู้อยากเห็นสิ่งที่อาจจะเป็นสถานการณ์ที่ทำให้คุณส่งข้อมูลบางอย่างในขณะที่ไม่ต้องการรับการบันทึกไว้สำหรับ"เหตุผลด้านความปลอดภัย" คุณส่งไปแล้ว!
นักบัญชี

1
@Accountant: ในสถานการณ์ของเขาผู้ใช้ออกจากระบบ ใครสามารถรับประกันได้ว่าผู้ใช้คนต่อไปใน User-Agent นั้นจะเป็นคนที่เพิ่งออกจากระบบ?
Fabien Haddadi

คำตอบ:


2578

บทนำ

ชุดขั้นต่ำที่ถูกต้องของส่วนหัวที่ทำงานในไคลเอนต์ที่กล่าวถึงทั้งหมด (และพร็อกซี่):

Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

Cache-Controlเป็นต่อข้อมูลจำเพาะ HTTP 1.1 สำหรับลูกค้าและผู้รับมอบฉันทะ (และโดยปริยายจำเป็นโดยลูกค้าบางส่วนติดกับExpires) Pragmaเป็นต่อข้อมูลจำเพาะสำหรับลูกค้ายุคก่อนประวัติศาสตร์ HTTP 1.0 Expiresเป็นต่อของ HTTP 1.0 และ 1.1 รายละเอียดสำหรับลูกค้าและผู้รับมอบฉันทะ ใน HTTP 1.1 Cache-Controlจะมีความสำคัญมากกว่าExpiresดังนั้นสำหรับ HTTP 1.0 proxies เท่านั้น

หากคุณไม่สนใจเกี่ยวกับ IE6 และการแคชที่ใช้งานไม่ได้เมื่อให้บริการหน้าเว็บผ่าน HTTPS เพียงอย่างเดียวno-storeคุณก็สามารถละเว้นCache-Control: no-cacheได้

Cache-Control: no-store, must-revalidate
Pragma: no-cache
Expires: 0

หากคุณไม่สนใจเกี่ยวกับไคลเอนต์ IE6 หรือ HTTP 1.0 (HTTP 1.1 ถูกนำมาใช้ในปี 1997) คุณสามารถละเว้นPragmaได้

Cache-Control: no-store, must-revalidate
Expires: 0

หากคุณไม่สนใจ HTTP พร็อกซี 1.0 เช่นกันคุณสามารถละเว้นExpiresได้

Cache-Control: no-store, must-revalidate

ในทางกลับกันหากเซิร์ฟเวอร์รวมDateส่วนหัวที่ถูกต้องโดยอัตโนมัติคุณก็สามารถละเว้นCache-Controlด้วยเหตุผลได้เช่นกันและพึ่งพาExpiresเท่านั้น

Date: Wed, 24 Aug 2016 18:32:02 GMT
Expires: 0

แต่นั่นอาจล้มเหลวหากเช่นผู้ใช้ปลายทางจัดการกับวันที่ของระบบปฏิบัติการและซอฟต์แวร์ไคลเอ็นต์นั้นใช้งานได้

Cache-Controlพารามิเตอร์อื่น ๆเช่นmax-ageไม่เกี่ยวข้องหากCache-Controlระบุพารามิเตอร์ข้างต้น Last-Modifiedส่วนหัวที่รวมไว้ในคำตอบอื่น ๆ ส่วนใหญ่ที่นี่เป็นเพียงที่น่าสนใจถ้าคุณต้องการจริงแคชคำขอเพื่อให้คุณไม่จำเป็นต้องระบุว่าที่ทุกคน

วิธีการตั้งค่า

ใช้ PHP:

header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1.
header("Pragma: no-cache"); // HTTP 1.0.
header("Expires: 0"); // Proxies.

ใช้ Java Servlet หรือ Node.js:

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setHeader("Expires", "0"); // Proxies.

ใช้ ASP.NET-MVC

Response.Cache.SetCacheability(HttpCacheability.NoCache);  // HTTP 1.1.
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.

ใช้ ASP.NET Web API:

// `response` is an instance of System.Net.Http.HttpResponseMessage
response.Headers.CacheControl = new CacheControlHeaderValue
{
    NoCache = true,
    NoStore = true,
    MustRevalidate = true
};
response.Headers.Pragma.ParseAdd("no-cache");
// We can't use `response.Content.Headers.Expires` directly
// since it allows only `DateTimeOffset?` values.
response.Content?.Headers.TryAddWithoutValidation("Expires", 0.ToString()); 

ใช้ ASP.NET:

Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.

ใช้ ASP.NET Core v3

// using Microsoft.Net.Http.Headers
Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate";
Response.Headers[HeaderNames.Expires] = "0";
Response.Headers[HeaderNames.Pragma] = "no-cache";

ใช้ ASP:

Response.addHeader "Cache-Control", "no-cache, no-store, must-revalidate" ' HTTP 1.1.
Response.addHeader "Pragma", "no-cache" ' HTTP 1.0.
Response.addHeader "Expires", "0" ' Proxies.

ใช้ Ruby on Rails หรือ Python / Flask:

headers["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1.
headers["Pragma"] = "no-cache" # HTTP 1.0.
headers["Expires"] = "0" # Proxies.

ใช้ Python / Django:

response["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1.
response["Pragma"] = "no-cache" # HTTP 1.0.
response["Expires"] = "0" # Proxies.

ใช้ Python / พีระมิด:

request.response.headerlist.extend(
    (
        ('Cache-Control', 'no-cache, no-store, must-revalidate'),
        ('Pragma', 'no-cache'),
        ('Expires', '0')
    )
)

ใช้งาน:

responseWriter.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
responseWriter.Header().Set("Pragma", "no-cache") // HTTP 1.0.
responseWriter.Header().Set("Expires", "0") // Proxies.

ใช้.htaccessไฟล์Apache :

<IfModule mod_headers.c>
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
</IfModule>

ใช้ HTML4:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">

แท็ก HTML เมตากับส่วนหัวการตอบสนอง HTTP

สิ่งสำคัญที่รู้ก็คือว่าเมื่อเพจ HTML จะทำหน้าที่มากกว่าการเชื่อมต่อ HTTP และส่วนหัวมีอยู่ในทั้งส่วนหัวของการตอบสนอง HTTP และแบบ HTML <meta http-equiv>แท็กแล้วหนึ่งที่ระบุไว้ในส่วนหัวของการตอบสนอง HTTP จะได้รับความสำคัญเหนือกว่าเมตาแท็กของ HTML เมตาแท็ก HTML จะใช้เฉพาะเมื่อดูหน้าเว็บจากระบบไฟล์ดิสก์ในระบบผ่านfile://URL ดูที่ข้อกำหนดเฉพาะ W3 HTML บทที่ 5.2.25.2.2 ระวังสิ่งนี้เมื่อคุณไม่ได้ระบุโดยทางโปรแกรมเนื่องจากเว็บเซิร์ฟเวอร์สามารถรวมค่าเริ่มต้นบางอย่างได้

โดยทั่วไปคุณจะไม่ควรระบุเมตาแท็ก HTML เพื่อหลีกเลี่ยงความสับสนโดยการเริ่มและพึ่งพาส่วนหัวการตอบกลับ HTTP ที่ยาก ยิ่งไปกว่านั้นโดยเฉพาะ<meta http-equiv>แท็กเหล่านั้นไม่ถูกต้องใน HTML5 อนุญาตเฉพาะhttp-equivค่าที่ระบุไว้ในข้อมูลจำเพาะ HTML5เท่านั้น

การตรวจสอบส่วนหัวการตอบสนอง HTTP จริง

หากต้องการตรวจสอบอีกรายการหนึ่งคุณสามารถดู / ตรวจแก้จุดบกพร่องได้ใน HTTP Traffic Monitor ของชุดเครื่องมือผู้พัฒนาเว็บเบราเซอร์ คุณสามารถไปที่นั่นได้โดยกด F12 ใน Chrome / Firefox23 + / IE9 + จากนั้นเปิดแผงแท็บ "เครือข่าย" หรือ "สุทธิ" แล้วคลิกคำขอ HTTP ที่น่าสนใจเพื่อเปิดเผยรายละเอียดทั้งหมดเกี่ยวกับคำขอ HTTP และการตอบสนอง ด้านล่างหน้าจอเป็นจาก Chrome:

เครื่องมือตรวจสอบปริมาณข้อมูล HTTP ของนักพัฒนาซอฟต์แวร์ Chrome แสดงส่วนหัวการตอบสนอง HTTP บน stackoverflow.com

ฉันต้องการตั้งค่าส่วนหัวเหล่านั้นในการดาวน์โหลดไฟล์ด้วย

ก่อนอื่นคำถามและคำตอบนี้กำหนดเป้าหมายไว้ที่ "หน้าเว็บ" (หน้า HTML) ไม่ใช่ "ดาวน์โหลดไฟล์" (PDF, zip, Excel, ฯลฯ ) คุณควรให้พวกเขาแคชและใช้ประโยชน์จากตัวระบุเวอร์ชันของไฟล์บางแห่งในพา ธ URI หรือการสอบถามเพื่อบังคับให้ทำการดาวน์โหลดซ้ำในไฟล์ที่ถูกเปลี่ยน เมื่อใช้ส่วนหัวที่ไม่มีแคชเหล่านั้นในการดาวน์โหลดไฟล์ให้ระวังข้อผิดพลาด IE7 / 8 เมื่อให้บริการดาวน์โหลดไฟล์ผ่าน HTTPS แทน HTTP ดูรายละเอียดได้ที่IE ไม่สามารถดาวน์โหลด foo.jsf IE ไม่สามารถเปิดเว็บไซต์นี้ได้ ไซต์ที่ร้องขอไม่พร้อมใช้งานหรือไม่สามารถพบได้


16
ดูเหมือนว่าจะไม่เสร็จสมบูรณ์ ฉันลองวิธีนี้บน IE 8 และพบว่าเบราว์เซอร์จะโหลดเวอร์ชันแคชเมื่อคุณกดปุ่มย้อนกลับ
Mike Ottum

16
ดูเหมือนว่าวิธีการทดสอบของคุณผิด บางทีหน้านั้นอยู่ในแคชอยู่แล้ว? บางทีส่วนหัวไม่ถูกต้อง / ถูก overriden? บางทีคุณกำลังดูคำขอผิด ฯลฯ ..
BalusC

8
ที่จริงแล้วฉันยืนยันว่าวิธีนี้ไม่สมบูรณ์และทำให้เกิดปัญหากับ IE8 หรืออย่างน้อยก็ในบางสถานการณ์ โดยเฉพาะอย่างยิ่งเมื่อใช้ IE8 เพื่อดึงทรัพยากรผ่าน SSL IE8 จะปฏิเสธการดึงทรัพยากรเป็นครั้งที่สอง (ไม่ว่าจะเลยหรือหลังจากการลองครั้งแรกขึ้นอยู่กับส่วนหัวที่ใช้) ดูบล็อก EricLaw ของตัวอย่างเช่น
haylem

21
ฉันต้องการเพิ่มว่านี่เป็นสิ่งที่ธนาคารแห่งอเมริกาทำ หากคุณดูที่ส่วนหัวการตอบสนองและแปลสิ่งนั้นลงใน aspx พวกเขากำลังทำ: Response.AppendHeader ("Cache-Control", "no-cache, no-store, ต้องตรวจสอบความถูกต้อง"); Response.AppendHeader ("หมดอายุ", "พฤ., 01 Dec 1994 16:00:00 GMT"); ฉันคิดว่าถ้ามันดีพอสำหรับพวกเขามันก็ดีพอสำหรับฉัน
จอห์น

8
@ John: นั่นหมดอายุส่วนหัวเป็นสิ่งคุ้มค่าเช่นในHTTP 1.0 มันใช้งานได้ แต่มันค่อนข้างไร้สาระที่จะใช้เวลาที่แน่นอน
BalusC

244

(เฮ้ทุกคน: โปรดอย่าคัดลอกและวางส่วนหัวทั้งหมดที่คุณสามารถหาได้โดยไม่สนใจ)

ก่อนอื่นประวัติปุ่มย้อนกลับไม่ใช่แคช :

ตัวแบบความสดใหม่ (ส่วน 4.2) ไม่ได้ใช้กับกลไกประวัติศาสตร์ นั่นคือกลไกประวัติสามารถแสดงการแสดงก่อนหน้านี้แม้ว่าจะหมดอายุแล้ว

ในข้อมูลจำเพาะ HTTP แบบเก่าถ้อยคำนั้นแข็งแกร่งยิ่งขึ้นบอกเบราว์เซอร์อย่างชัดเจนว่าไม่สนใจคำสั่งแคชสำหรับประวัติปุ่มย้อนกลับ

ย้อนกลับควรย้อนเวลากลับไป (จนถึงเวลาที่ผู้ใช้เคยเป็นบันทึกไว้ใน) มันไม่ได้นำทางไปยัง URL ที่เปิดก่อนหน้านี้

อย่างไรก็ตามในทางปฏิบัติแคชสามารถมีผลต่อปุ่มย้อนกลับในสถานการณ์ที่เฉพาะเจาะจงมาก:

  • หน้าจะต้องส่งผ่านHTTPSมิฉะนั้นแคชนี้จะไม่เป็นที่น่าเชื่อถือ นอกจากนี้หากคุณไม่ได้ใช้ HTTPS หน้าเว็บของคุณจะเสี่ยงต่อการขโมยข้อมูลเข้าสู่ระบบด้วยวิธีอื่น ๆ
  • คุณต้องส่งCache-Control: no-store, must-revalidate(บางเบราว์เซอร์สังเกตno-storeและบางสังเกตmust-revalidate)

คุณไม่จำเป็นต้อง:

  • <meta>กับส่วนหัวของแคช - มันไม่ทำงานเลย ไร้ประโยชน์โดยสิ้นเชิง
  • post-check/ pre-check- มัน IE เท่านั้นสั่งที่ใช้เฉพาะกับcachableทรัพยากร
  • ส่งส่วนหัวเดียวกันสองครั้งหรือในส่วนโหล ตัวอย่าง PHP บางส่วนนั้นแทนที่ส่วนหัวก่อนหน้านี้ส่งผลให้มีการส่งเฉพาะส่วนสุดท้ายเท่านั้น

หากคุณต้องการคุณสามารถเพิ่ม:

  • no-cacheหรือmax-age=0ซึ่งจะทำให้ทรัพยากร (URL) "ค้าง" และต้องการให้เบราว์เซอร์ตรวจสอบกับเซิร์ฟเวอร์หากมีเวอร์ชันที่ใหม่กว่า (no-storeหมายถึงนี้แล้วแข็งแกร่งยิ่งขึ้น)
  • Expiresกับวันที่ในอดีตสำหรับ HTTP / 1.0 ลูกค้า (แม้ว่าจริง HTTP / ลูกค้า 1.0 เท่านั้นจะสมบูรณ์ไม่ได้มีอยู่วันนี้)

โบนัส: ใหม่แคช HTTP RFC


1
สิ่งนี้จะมีผลข้างเคียงกับประสิทธิภาพของเว็บไซต์ในแง่ของเวลาในการโหลดหรือไม่ วิธีที่ไม่มีการจัดเก็บไม่มีแคชต้องตรวจสอบความถูกต้องใหม่จะส่งผลกระทบต่อประสิทธิภาพการทำงานอย่างไร
Raman Ghai

@RamanGhai โดยทั่วไปการปิดใช้งานแคชจะส่งผลเสียต่อประสิทธิภาพการทำงาน (และตัวเลือกทั้ง 3 ตัวที่คุณกล่าวถึงคือปิดการใช้งานแคช) มันอาจทำให้ผู้รับมอบฉันทะ CDN และ ISP (เช่นผู้ให้บริการโทรศัพท์มือถือทั่วไปใช้) ไม่ได้ผล ไม่เจ็บผู้ใช้ใหม่โหลดครั้งแรก (นอกเหนือจากปัญหาพร็อกซี) แต่แล้วการนำทางที่ตามมาอาจช้ากว่ามาก
Kornel

@porneL Cache-Control: must-revalidateคุณรัฐว่าเราจะต้องส่ง ทำไมไม่ส่งCache-Control: no-cacheตั้งแต่no-cacheบอกเป็นนัยแล้วmust-revalidate? w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1
Pacerier

3
@Pierier ความสัมพันธ์ของno-cachewith must-revalidateเป็นจริงสำหรับแคช แต่ประวัติย้อนหลังไม่ใช่แคช เบราว์เซอร์กรณีพิเศษอย่างชัดเจนmust-revalidateกับพฤติกรรมประวัติศาสตร์การควบคุม
Kornel

@ porneL อืมมี RFC ที่สนับสนุนซึ่งระบุว่าเป็นพฤติกรรมที่ต้องการหรือไม่
Pacerier

103

ตามที่ @Kornel ระบุไว้สิ่งที่คุณต้องการไม่ใช่เพื่อปิดใช้งานแคช แต่เพื่อปิดใช้งานบัฟเฟอร์ประวัติ เบราว์เซอร์ที่แตกต่างกันมีวิธีที่ละเอียดอ่อนในการปิดใช้งานบัฟเฟอร์ประวัติ

ใน Chrome (v28.0.1500.95 เมตร) Cache-Control: no-storeเราสามารถทำเช่นนี้โดยเฉพาะ

ใน FireFox (v23.0.1) หนึ่งในสิ่งเหล่านี้จะทำงาน:

  1. Cache-Control: no-store

  2. Cache-Control: no-cache (https เท่านั้น)

  3. Pragma: no-cache (https เท่านั้น)

  4. Vary: * (https เท่านั้น)

ใน Opera (v12.15) เราสามารถทำได้โดยCache-Control: must-revalidate(https เท่านั้น)

ใน Safari (v5.1.7, 7534.57.2) สิ่งเหล่านี้จะใช้ได้:

  1. Cache-Control: no-store
    <body onunload=""> ใน html

  2. Cache-Control: no-store (https เท่านั้น)

ใน IE8 (v8.0.6001.18702IC) สิ่งใดสิ่งหนึ่งเหล่านี้จะทำงาน:

  1. Cache-Control: must-revalidate, max-age=0

  2. Cache-Control: no-cache

  3. Cache-Control: no-store

  4. Cache-Control: must-revalidate
    Expires: 0

  5. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT

  6. Pragma: no-cache (https เท่านั้น)

  7. Vary: * (https เท่านั้น)

การรวมข้างต้นทำให้เราได้โซลูชันนี้ซึ่งใช้งานได้กับ Chrome 28, FireFox 23, IE8, Safari 5.1.7 และ Opera 12.15: Cache-Control: no-store, must-revalidate (https เท่านั้น)

โปรดทราบว่าจำเป็นต้องมี https เนื่องจาก Opera จะไม่ปิดใช้งานบัฟเฟอร์ประวัติสำหรับหน้าเว็บ http ธรรมดา หากคุณไม่สามารถรับ https และคุณพร้อมที่จะเพิกเฉยต่อ Opera สิ่งที่ดีที่สุดที่คุณสามารถทำได้คือ:

Cache-Control: no-store
<body onunload="">

ด้านล่างแสดงบันทึกดิบของการทดสอบของฉัน:

http:

  1. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  2. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  3. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    ล้มเหลว: Safari 5.1.7, Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8

  4. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    ล้มเหลว: Safari 5.1.7, Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8

  5. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  6. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  7. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  8. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  9. Cache-Control: no-store
    ล้มเหลว: Safari 5.1.7, Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8

  10. Cache-Control: no-store
    <body onunload="">
    ล้มเหลว: Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  11. Cache-Control: no-cache
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  12. Vary: *
    ล้มเหลว: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    สำเร็จ: ไม่มี

  13. Pragma: no-cache
    ล้มเหลว: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    สำเร็จ: ไม่มี

  14. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  15. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  16. Cache-Control: must-revalidate, max-age=0
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  17. Cache-Control: must-revalidate
    Expires: 0
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  18. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    สำเร็จ: IE8

  19. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    สำเร็จ: ไม่มี

HTTPS:

  1. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    สำเร็จ: ไม่มี

  2. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    สำเร็จ: ไม่มี

  3. Vary: *
    ล้มเหลว: Chrome 28, Safari 5.1.7, Opera 12.15
    สำเร็จ: FireFox 23, IE8

  4. Pragma: no-cache
    ล้มเหลว: Chrome 28, Safari 5.1.7, Opera 12.15
    สำเร็จ: FireFox 23, IE8

  5. Cache-Control: no-cache
    ล้มเหลว: Chrome 28, Safari 5.1.7, Opera 12.15
    สำเร็จ: FireFox 23, IE8

  6. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    ล้มเหลว: Chrome 28, Safari 5.1.7, Opera 12.15
    สำเร็จ: FireFox 23, IE8

  7. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    ล้มเหลว: Chrome 28, Safari 5.1.7, Opera 12.15
    สำเร็จ: FireFox 23, IE8

  8. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    ล้มเหลว: Chrome 28, Safari 5.1.7, Opera 12.15
    สำเร็จ: FireFox 23, IE8

  9. Cache-Control: must-revalidate
    ล้มเหลว: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    สำเร็จ: Opera 12.15

  10. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    สำเร็จ: Opera 12.15

  11. Cache-Control: must-revalidate, max-age=0
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7
    สำเร็จ: IE8, Opera 12.15

  12. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, Safari 5.1.7
    สำเร็จ: FireFox 23, IE8, Opera 12.15

  13. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Chrome 28, Safari 5.1.7
    สำเร็จ: FireFox 23, IE8, Opera 12.15

  14. Cache-Control: no-store
    ล้มเหลว: Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  15. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  16. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    ล้มเหลว: Opera 12.15
    สำเร็จ: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  17. Cache-Control: private, no-cache
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    ล้มเหลว: Chrome 28, Safari 5.1.7, Opera 12.15
    สำเร็จ: FireFox 23, IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7,
    สำเร็จ: IE8, Opera 12.15

  19. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7,
    สำเร็จ: IE8, Opera 12.15

  20. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7,
    สำเร็จ: IE8, Opera 12.15

  21. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    ล้มเหลว: Chrome 28, FireFox 23, Safari 5.1.7,
    สำเร็จ: IE8, Opera 12.15

  22. Cache-Control: private, must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    ล้มเหลว: Chrome 28, Safari 5.1.7
    สำเร็จ: FireFox 23, IE8, Opera 12.15

  23. Cache-Control: no-store, must-revalidate
    ล้มเหลว: ไม่
    สำเร็จ: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15


3
ฉันรู้ว่านี่ถูกโพสต์เมื่อสองสามปีก่อน แต่มันเป็นการอ่านที่น่าสนใจ ปัญหานี้ทำให้ฉันคลั่งไคล้ไม่กี่เดือนแล้วร่างกายดูเหมือนจะรู้วิธีจัดการกับการควบคุมแคช ฉันเห็นผู้ใช้ไม่กี่คน<body onunload="">แต่ดูเหมือนว่าจะเป็นปัญหาที่แท้จริงมากขึ้น ฉันได้ลองใช้. htaccess และแก้ไขส่วนหัวด้วยวิธีนี้หรือไม่หากฉันใช้ HTTPS ซาฟารีส่วนใหญ่เป็นที่ที่ปัญหาจัดมากที่สุด
Jordan

4
@ จอร์แดนต่อบันทึกข้างต้นหากคุณมี HTTPS แล้วการเพิ่มCache-Control: no-storeจะทำเคล็ดลับ <body onunload="">จำเป็นเฉพาะเมื่อคุณไม่มี HTTPS
Pacerier

37

ฉันพบว่าเส้นทาง web.config มีประโยชน์ (พยายามเพิ่มไปยังคำตอบ แต่ดูเหมือนจะไม่ได้รับการยอมรับดังนั้นโพสต์ที่นี่)

<configuration>
<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Cache-Control" value="no-cache, no-store, must-revalidate" />
            <!-- HTTP 1.1. -->
            <add name="Pragma" value="no-cache" />
            <!-- HTTP 1.0. -->
            <add name="Expires" value="0" />
            <!-- Proxies. -->
        </customHeaders>
    </httpProtocol>
</system.webServer>

และนี่คือวิธีด่วน / node.js ในการทำสิ่งเดียวกัน:

app.use(function(req, res, next) {
    res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    res.setHeader('Pragma', 'no-cache');
    res.setHeader('Expires', '0');
    next();
});

สำหรับ web.config ฉันจะแก้ไขเพียงเล็กน้อยเพื่อใช้ส่วนหัวที่กำหนดเองเฉพาะกับสคริปต์ที่เรารู้ว่ามีการโหลดแบบไดนามิก / ใช้ requirejs สมมติว่าสคริปต์ของคุณพบในโฟลเดอร์ไคลเอนต์: <location path = "client"> ..... </location>
อิบราฮิมเบ็นซาลา

สำหรับผู้ที่อาจสงสัยว่าweb.confคืออะไร: มันคือการตั้งค่าหลักและไฟล์กำหนดค่าสำหรับASP.NETโปรแกรมประยุกต์บนเว็บ มันเป็นเอกสาร XML ที่อยู่ในไดเรกทอรีราก ( วิกิ )
อีก

27

ฉันพบว่าคำตอบทั้งหมดในหน้านี้ยังคงมีปัญหา โดยเฉพาะอย่างยิ่งฉันสังเกตเห็นว่าไม่มีใครในพวกเขาจะหยุด IE8 จากการใช้หน้าแคชรุ่นเมื่อคุณเข้าถึงได้โดยกดปุ่มย้อนกลับ

หลังจากการวิจัยและการทดสอบมากมายฉันพบว่ามีสองหัวที่ฉันต้องการจริงๆคือ:

การควบคุมแคช: ไม่มีการ
เปลี่ยนแปลง: *

สำหรับคำอธิบายของส่วนหัวต่าง ๆ ให้ดูที่ 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 ดูที่ BalusC ของคำตอบ


4
ใช้งานได้กับปุ่มย้อนกลับของ IE8 !! หลังจากลองทุกอย่างในคำแนะนำอื่น ๆ การเพิ่มส่วนหัว "Vary: *" เป็นสิ่งเดียวที่สามารถบังคับให้ IE8 โหลดหน้าเว็บซ้ำได้เมื่อผู้ใช้กดปุ่มย้อนกลับ และใช้งานได้บนเซิร์ฟเวอร์ HTTP / 1.1
coredumperror

รวมกับส่วนหัวที่แนะนำโดย BarlusC รวมถึง JS snippet ที่เรียก window.location.reload () เมื่อเหตุการณ์ onPageShow ทริกเกอร์ด้วยแอตทริบิวต์ "persisted" (จำเป็นสำหรับ Safari) เบราว์เซอร์ทุกตัวที่ฉันทดสอบประสบความสำเร็จในการโหลดซ้ำจาก เซิร์ฟเวอร์เมื่อผู้ใช้ใช้ปุ่มย้อนกลับ
coredumperror

1
@CoreDumpError คุณไม่ควรเปิดใช้งาน JavaScript
Pacerier

@Pacerier ในขณะที่ฉันเขียนคำตอบในปี 2010 สิ่งนี้ใช้ได้กับเวอร์ชันล่าสุดของทั้ง Safari และ Opera โดยที่เซิร์ฟเวอร์ของเราระบุว่าตัวเองเป็นเซิร์ฟเวอร์ HTTP 1.0 น่าเสียดายที่ฉันไม่มีวิธีทดสอบอย่างง่ายดายอีกต่อไปดังนั้นฉันจึงไม่สามารถบอกอะไรได้อย่างชัดเจนเกี่ยวกับเบราว์เซอร์เวอร์ชันล่าสุด
Chris Vasselli

เวอร์ชันของเบราว์เซอร์ที่คุณทดสอบมีอะไรบ้าง
Pacerier

21

หลังจากการวิจัยเล็กน้อยเราพบรายการส่วนหัวต่อไปนี้ซึ่งดูเหมือนจะครอบคลุมเบราว์เซอร์ส่วนใหญ่:

ใน 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


36
@bart: ยิ่งลำบากมากขึ้นคือวันที่ 26 กรกฎาคมในปี 1997 เป็นวันเสาร์ไม่ใช่วันจันทร์ ...
Cᴏʀʏ

5
Cache-Control: no-cacheและการCache-Control: privateปะทะกัน - คุณไม่ควรรวมทั้งสองอย่างเข้าด้วยกัน: อดีตบอกเบราว์เซอร์และพร็อกซี่ไม่ให้แคชเลยหลังบอกพร็อกซีไม่ให้แคช แต่ให้เบราว์เซอร์ถือสำเนาส่วนตัวของตัวเอง ฉันไม่แน่ใจว่าการตั้งค่าเบราว์เซอร์ใดจะตามมา แต่ไม่น่าจะสอดคล้องกันระหว่างเบราว์เซอร์และเวอร์ชัน
Keith

อย่าใช้การตรวจสอบล่วงหน้าและตรวจสอบภายหลัง blogs.msdn.com/b/ieinternals/archive/2009/07/20/…
EricLaw

สิ่งนี้ใช้ไม่ได้สำหรับฉัน - โดยใช้ asp.net 4.5 โค้ดจะทำงาน แต่ไม่ได้ผลลัพธ์ตามที่ต้องการ ฉันต้องทำตามนี้: stackoverflow.com/questions/22443932/…
Andy

8

การใช้ส่วนหัว pragma ในการตอบสนองเป็นเรื่องภรรยา RFC2616 กำหนดไว้เป็นส่วนหัวคำขอเท่านั้น

http://www.mnot.net/cache_docs/#PRAGMA


4
นี่เป็นตัวอย่างที่ดีว่าทำไมคุณต้องก้าวข้ามข้อกำหนด หากรายละเอียดชัดเจนเสมอจะไม่มีจุดสำหรับไซต์เช่น StackOverflow จากMicrosoft เพื่อวัตถุประสงค์ในการเข้ากันได้ย้อนหลังกับเซิร์ฟเวอร์ HTTP 1.0, Internet Explorer รองรับการใช้งานพิเศษของ HTTP Pragma: no-cache header หากไคลเอ็นต์สื่อสารกับเซิร์ฟเวอร์ผ่านการเชื่อมต่อที่ปลอดภัย (https: //) และเซิร์ฟเวอร์จะส่งคืนส่วนหัวของ Pragma: no-cache พร้อมการตอบสนอง Internet Explorer จะไม่แคชการตอบสนอง
michaelok

@michaelok: การอ้างอิงของคุณถูกต้อง แต่พลาดจุดที่ใหญ่กว่า - ตั้งค่า Cache-Control / Expires ที่เหมาะสมและคุณไม่จำเป็นต้องใช้ pragma
EricLaw

8

การปฏิเสธความรับผิด: ฉันขอแนะนำให้อ่านคำตอบของ @ 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);

ดูเอกสารที่สมบูรณ์มากขึ้นที่นี่


14
นี่เต็มไปด้วยตำนาน การตรวจสอบล่วงหน้าและการตรวจสอบภายหลังเป็นเพียงอย่างเดียวเท่านั้นที่เกี่ยวข้องกับการตอบกลับที่แคชไว้เท่านั้นและค่า 0 คือไม่ใช้งาน max-stale เป็นส่วนหัวคำขอพร็อกซีไม่ใช่ส่วนหัวการตอบสนองของเซิร์ฟเวอร์ หมดอายุยอมรับค่าเดียวเท่านั้น มากกว่าหนึ่งจะทำให้ส่วนหัวนี้จะถูกละเว้น
Kornel

1
@porneL คุณจะส่งคำตอบการแข่งขันที่เกี่ยวข้องกับตำนานเหล่านี้อย่างถูกต้องหรือไม่?
Oddthinking

@Oddthinking ดูเหมือนว่าstackoverflow.com/questions/49547/…เป็นคำตอบที่แข่งขันกัน
Mike Ottum

@Pierier ใช่อย่างที่ฉันบอกในข้อจำกัดความรับผิดชอบใช้คำตอบของ BalusC
Steven Oxley

8

สำหรับ ASP.NET Core ให้สร้างคลาสมิดเดิลแวร์แบบง่าย:

public class NoCacheMiddleware
{
    private readonly RequestDelegate m_next;

    public NoCacheMiddleware( RequestDelegate next )
    {
        m_next = next;
    }

    public async Task Invoke( HttpContext httpContext )
    {
        httpContext.Response.OnStarting( ( state ) =>
        {
            // ref: http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers
            httpContext.Response.Headers.Append( "Cache-Control", "no-cache, no-store, must-revalidate" );
            httpContext.Response.Headers.Append( "Pragma", "no-cache" );
            httpContext.Response.Headers.Append( "Expires", "0" );
            return Task.FromResult( 0 );
        }, null );

        await m_next.Invoke( httpContext );
    }
}

จากนั้นลงทะเบียนด้วย Startup.cs

app.UseMiddleware<NoCacheMiddleware>();

ตรวจสอบให้แน่ใจว่าคุณเพิ่มสิ่งนี้หลังจาก

app.UseStaticFiles();

ฉันขอแนะนำให้ใช้ค่าคงที่จาก Microsoft.Net.Http.Headers.HeaderNames แทนตัวอักษรสตริง "Cache-Controls", "Pragma" และ "Expires"
Victor Sharovatov

7

คำสั่งเหล่านี้ไม่ได้ช่วยลดความเสี่ยงด้านความปลอดภัย พวกเขาตั้งใจจะบังคับให้ UA ทำการรีเฟรชข้อมูลที่มีความผันผวนโดยไม่ทำให้ UA ไม่สามารถเก็บข้อมูลได้ ดูคำถามที่คล้ายกันนี้ อย่างน้อยที่สุดไม่มีการรับประกันว่าเราเตอร์พร็อกซี่และอื่น ๆ จะไม่เพิกเฉยต่อคำสั่งแคชเช่นกัน

ในแง่บวกมากขึ้นนโยบายเกี่ยวกับการเข้าถึงทางกายภาพไปยังคอมพิวเตอร์การติดตั้งซอฟต์แวร์และสิ่งที่คล้ายกันจะทำให้คุณก้าวไปข้างหน้า บริษัท ส่วนใหญ่ในแง่ของความปลอดภัย หากผู้บริโภคของข้อมูลนี้เป็นสมาชิกของสาธารณะสิ่งเดียวที่คุณทำได้คือช่วยให้พวกเขาเข้าใจว่าเมื่อข้อมูลถูกกระทบกับเครื่องของพวกเขาเครื่องนั้นเป็นความรับผิดชอบของพวกเขาไม่ใช่ของคุณ


7

มีข้อบกพร่องใน IE6

เนื้อหาที่มี "การเข้ารหัสเนื้อหา: gzip" จะถูกเก็บไว้เสมอแม้ว่าคุณจะใช้ "การควบคุมแคช: ไม่มีแคช"

http://support.microsoft.com/kb/321722

คุณสามารถปิดใช้งานการบีบอัด gzip สำหรับผู้ใช้ IE6 (ตรวจสอบตัวแทนผู้ใช้สำหรับ "MSIE 6")


6

RFC สำหรับHTTP 1.1บอกว่าวิธีการที่เหมาะสมคือการเพิ่ม HTTP Header สำหรับ:

การควบคุมแคช: ไม่มีแคช

เบราว์เซอร์ที่เก่ากว่าอาจละเว้นสิ่งนี้หากพวกเขาไม่สอดคล้องกับ HTTP 1.1 สำหรับสิ่งที่คุณสามารถลองใช้ส่วนหัว:

Pragma: ไม่มีแคช

สิ่งนี้ควรใช้กับเบราว์เซอร์ HTTP 1.1 ด้วย


1
สเป็คบ่งชี้ว่าการตอบสนองจะต้องไม่นำมาใช้ใหม่โดยไม่ต้องตรวจสอบใหม่ มันเป็น Cache-Control: no-store ซึ่งเป็นวิธีการอย่างเป็นทางการเพื่อระบุว่าการตอบสนองที่ไม่ได้ถูกเก็บไว้ในแคชในตอนแรก
AnthonyWJones

6

การตั้งค่าส่วนหัว http ที่ถูกดัดแปลงเป็นบางวันในปี 1995 มักจะเป็นการหลอกลวง

นี่คือตัวอย่าง:

หมดอายุ: พุธ, 15 พ.ย. 1995 04:58:08 GMT
แก้ไขครั้งล่าสุด: พุธ, 15 พ.ย. 1995 04:58:08 GMT
การควบคุมแคช: ไม่มีแคช, ต้องตรวจสอบความถูกต้องอีกครั้ง

1
การตั้งค่า Last-Last Last-Modified ไม่มีผลกระทบกับการแคชนอกจากการปล่อยให้การตอบสนองที่แคชไว้ใช้งานได้นานขึ้นเนื่องจากการตรวจสอบความถูกต้องแบบฮิวริสติก
EricLaw

6

เอกสาร 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);

11
เห็นได้ชัดว่ามันผิด การเรียกไปที่ส่วนหัว () สำหรับ Expires, Cache-control และ Pragma ที่เขียนทับค่าที่ตั้งไว้ก่อนหน้า
Kornel

1
@porneL: ไม่มีการไม่เขียนทับค่าที่ตั้งไว้ก่อนหน้านี้ในขณะที่เขาส่งเท็จเป็นพารามิเตอร์ที่ 2 โดยบอกว่าจะไม่แทนที่ค่าก่อนหน้า
Julien Palard

1
@JulienPalard คำตอบถูกแก้ไขหลังจากที่ฉันแสดงความคิดเห็น มันยังไม่สมเหตุสมผล
Kornel

อย่าส่งส่วนหัวของ Cache-Control หลายตัวหากคุณต้องการทำงานใน IE ก่อน 9 ไม่เคยส่งเช็คก่อนหรือหลังเช็ค blogs.msdn.com/b/ieinternals/archive/2009/07/20/…
EricLaw

6

หากคุณกำลังประสบปัญหาการดาวน์โหลดกับ IE6-IE8 ผ่าน SSL และแคช: ไม่มีส่วนหัวแคช (และค่าที่คล้ายกัน) กับไฟล์ MS Office คุณสามารถใช้แคช: ส่วนตัวไม่มีส่วนหัวที่ร้านค้าและส่งคืนไฟล์ตามคำขอ POST มันได้ผล.


6

ในกรณีของฉันฉันแก้ไขปัญหาใน chrome ด้วยสิ่งนี้

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

ที่ฉันต้องล้างเนื้อหาของข้อมูลในรูปแบบ previus เมื่อผู้ใช้คลิกปุ่มย้อนกลับเพื่อความปลอดภัย


ปัญหาเบราว์เซอร์ mozilla 19.x ของฉันยังได้รับการแก้ไขโดยข้อมูลโค้ด การเติมข้อความอัตโนมัติ = "ปิด" ขอบคุณ.
Satya

5

คำตอบที่ยอมรับไม่ได้ทำงานกับ IIS7 + ไปโดยคำถามมากมายเกี่ยวกับส่วนหัวของแคชที่ไม่ได้ถูกส่งใน II7:

และอื่น ๆ

คำตอบที่ยอมรับนั้นถูกต้องซึ่งจะต้องตั้งค่าส่วนหัว แต่ไม่ใช่ในวิธีที่ต้องตั้งค่า วิธีนี้ใช้ได้กับ IIS7:

Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "-1");

บรรทัดแรกตั้งค่าCache-controlเป็นno-cacheและบรรทัดที่สองเพิ่มแอตทริบิวต์อื่น ๆno-store, must-revalidate


งานนี้สำหรับฉัน:Response.Cache.SetAllowResponseInBrowserHistory(false); Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
Vilx-

4

ฉันได้ผลลัพธ์ที่ดีที่สุดและสม่ำเสมอที่สุดในทุกเบราว์เซอร์โดยการตั้งค่า Pragma: no-cache


4

ส่วนหัวในคำตอบที่จัดทำโดย BalusC ไม่ได้ป้องกัน Safari 5 (และอาจเป็นเวอร์ชั่นที่เก่ากว่า) แสดงเนื้อหาจากแคชของเบราว์เซอร์เมื่อใช้ปุ่มย้อนกลับของเบราว์เซอร์ วิธีป้องกันสิ่งนี้คือการเพิ่มแอตทริบิวต์ตัวจัดการเหตุการณ์ onunload ที่ว่างลงในแท็ก body:

<body onunload=""> 

เห็นได้ชัดว่าการแฮ็กนี้ทำลายแคชแบ็คเอนด์ใน Safari: มีเหตุการณ์การโหลดข้ามเบราว์เซอร์เมื่อคลิกปุ่มย้อนกลับหรือไม่


เยี่ยมมากฉันได้ทำการทดสอบและใช้งานได้จริงกับ Safari (5.1.7) แต่ไม่ใช่ Opera
Pacerier

4

ตรวจสอบให้แน่ใจว่าคุณรีเซ็ตไฟล์ExpiresDefaultของคุณ.htaccessหากคุณใช้วิธีนี้เพื่อเปิดใช้งานการแคช

ExpiresDefault "access plus 0 seconds"

หลังจากนั้นคุณสามารถใช้ExpiresByTypeเพื่อตั้งค่าเฉพาะสำหรับไฟล์ที่คุณต้องการแคช:

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

สิ่งนี้อาจมีประโยชน์หากไฟล์ไดนามิกของคุณเช่น php และอื่น ๆ ถูกเบราว์เซอร์ถูกแคชและคุณไม่สามารถหาสาเหตุได้ ExpiresDefaultตรวจสอบ


3

นอกเหนือไปจากส่วนหัวพิจารณาการให้บริการหน้าของคุณผ่านทางhttps เบราว์เซอร์จำนวนมากจะไม่แคช https โดยค่าเริ่มต้น


3
//In .net MVC
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult FareListInfo(long id)
{
}

// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>

2

เพื่อให้BalusC -> คำตอบ ถ้าคุณใช้ Perl คุณสามารถใช้ CGI เพื่อเพิ่มส่วนหัว HTTP

ใช้ Perl:

Use CGI;    
sub set_new_query() {
        binmode STDOUT, ":utf8";
        die if defined $query;
        $query = CGI->new();
        print $query->header(
                        -expires       => 'Sat, 26 Jul 1997 05:00:00 GMT',
                        -Pragma        => 'no-cache',
                        -Cache_Control => join(', ', qw(
                                            private
                                            no-cache
                                            no-store
                                            must-revalidate
                                            max-age=0
                                            pre-check=0
                                            post-check=0 
                                           ))
        );
    }

ใช้ apache httpd.conf

<FilesMatch "\.(html|htm|js|css|pl)$">
FileETag None
<ifModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</ifModule>

หมายเหตุ:เมื่อฉันพยายามใช้ html META เบราว์เซอร์จะไม่สนใจและแคชหน้าเว็บ


0

ฉันแค่ต้องการชี้ให้เห็นว่าถ้าใครบางคนต้องการป้องกันการแคชเนื้อหาแบบไดนามิกเท่านั้นการเพิ่มส่วนหัวเพิ่มเติมเหล่านั้นควรทำโดยทางโปรแกรม

ฉันแก้ไขไฟล์การกำหนดค่าของโครงการของฉันเพื่อเพิ่มส่วนหัวที่ไม่แคช แต่ยังปิดการใช้งานการแคชเนื้อหาแบบคงที่ซึ่งมักไม่ต้องการ การดัดแปลงส่วนหัวการตอบสนองในโค้ดทำให้มั่นใจได้ว่ารูปภาพและไฟล์สไตล์จะถูกแคช

นี้ค่อนข้างชัดเจน แต่ก็ยังมีมูลค่าการกล่าวขวัญ

และอีกข้อควรระวัง ระวังการใช้วิธี ClearHeaders จากคลาส HttpResponse มันอาจทำให้คุณมีรอยฟกช้ำถ้าคุณใช้มันอย่างประมาท เหมือนมันให้ฉัน

หลังจากเปลี่ยนเส้นทางในเหตุการณ์ ActionFilterAttribute ผลที่ตามมาของการล้างส่วนหัวทั้งหมดจะสูญเสียข้อมูลเซสชันและข้อมูลทั้งหมดในที่เก็บ TempData การเปลี่ยนเส้นทางจากการกระทำนั้นปลอดภัยกว่าหรือไม่ล้างส่วนหัวเมื่อมีการเปลี่ยนเส้นทาง

ในความคิดที่สองฉันไม่สนับสนุนให้ใช้วิธีการ ClearHeaders เป็นการดีกว่าที่จะลบส่วนหัวแยกกัน และเพื่อตั้งค่าส่วนหัวของ Cache-Control อย่างถูกต้องฉันใช้รหัสนี้:

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

0

ฉันไม่มีโชคกับ<head><meta>องค์ประกอบ การเพิ่มพารามิเตอร์ HTTP ที่เกี่ยวข้องกับแคชโดยตรง (นอกเอกสาร HTML) จะใช้งานได้จริงสำหรับฉัน

โค้ดตัวอย่างใน Python โดยใช้การweb.headerโทรผ่านweb.py ฉันตั้งใจ redacted รหัสโปรแกรมอรรถประโยชน์ที่ไม่เกี่ยวข้องส่วนบุคคลของฉัน

    นำเข้าเว็บ
    sys นำเข้า
    นำเข้าส่วนบุคคล - ยูทิลิตี้

    myname = "main.py"

    URL = (
        '/', 'main_class'
    )

    main = web.application (URL, globals ())

    render = web.template.render ("เทมเพลต /", ฐาน = "เลย์เอาต์", แคช = เท็จ)

    ชั้น main_class (วัตถุ):
        def GET (ตัวเอง):
            web.header ("Cache-control", "no-cache, no-store, ต้องตรวจสอบความถูกต้อง")
            web.header ("Pragma", "no-cache")
            web.header ("หมดอายุ", "0")
            return render.main_form ()

        def POST (ตัวเอง):
            msg = "โพสต์แล้ว:"
            form = web.input (function = None)
            web.header ("Cache-control", "no-cache, no-store, ต้องตรวจสอบความถูกต้อง")
            web.header ("Pragma", "no-cache")
            web.header ("หมดอายุ", "0")
            return render.index_laid_out (ทักทาย = msg + form.function)

    ถ้า __name__ == "__main__":
        nargs = len (sys.argv)
        # ตรวจสอบให้แน่ใจว่ามีข้อโต้แย้งเพียงพอหลังจากชื่อโปรแกรมไพ ธ อน
        if nargs! = 2:
            LOG-AND-DIE ("% s: ข้อผิดพลาดของบรรทัดคำสั่ง nargs =% s ควรเป็น 2", myname, nargs)
        # ตรวจสอบให้แน่ใจว่าหมายเลขพอร์ต TCP เป็นตัวเลข
        ลอง:
            tcp_port = int (sys.argv [1])
        ยกเว้นเป็น e:
            LOG-AND-DIE ("% s: tcp_port = int (% s) ล้มเหลว (ไม่ใช่จำนวนเต็ม)", myname, sys.argv [1])
        # ทั้งหมดเป็นอย่างดี!
        JUST-LOG ("% s: ทำงานบนพอร์ต% d", myname, tcp_port)
        web.httpserver.runsimple (main.wsgifunc (), ("localhost", tcp_port))
        main.run ()


สิ่งนี้ไม่ได้ครอบคลุมหลายครั้งแล้วในคำตอบที่อยู่บนเว็บไซต์มานานหลายปีหรือไม่?
Martin Tournoij

คำสั่ง META ทำงานใน Internet Explorer และรุ่น Edge 18 และรุ่นก่อนหน้า เบราว์เซอร์สมัยใหม่ไม่สนับสนุนพวกเขา crbug.com/2763
EricLaw

0

ดูลิงค์นี้เพื่อกรณีศึกษาเกี่ยวกับแคช:

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

ข้อมูลสรุปตามบทความใช้Cache-Control: no-storeงานได้กับ Chrome, Firefox และ IE เท่านั้น IE ยอมรับการควบคุมอื่น ๆ แต่ Chrome และ Firefox ทำไม่ได้ ลิงค์นี้เป็นแบบอ่านที่ดีพร้อมประวัติความเป็นมาของการแคชและการจัดทำเอกสารของแนวคิด


0

ไม่แน่ใจว่าคำตอบของฉันฟังดูง่ายและงี่เง่าและบางทีคุณอาจเคยรู้จักมานานแล้ว แต่เนื่องจากการป้องกันไม่ให้ใครบางคนใช้ปุ่มย้อนกลับของเบราว์เซอร์เพื่อดูหน้าประวัติศาสตร์ของคุณเป็นหนึ่งในเป้าหมายของคุณคุณสามารถใช้:

window.location.replace("https://www.example.com/page-not-to-be-viewed-in-browser-history-back-button.html");

แน่นอนว่าสิ่งนี้อาจเป็นไปไม่ได้ที่จะนำไปใช้กับทั้งไซต์ แต่อย่างน้อยสำหรับหน้าสำคัญบางหน้าคุณสามารถทำได้ หวังว่านี่จะช่วยได้


-1

คุณสามารถใช้ที่ตั้งบล็อกเพื่อตั้งค่าไฟล์แยกต่างหากแทนที่จะเป็นทั้งแอพรับการแคชใน IIS

 <location path="index.html">
    <system.webServer>
      <httpProtocol>
        <customHeaders>
          <add name="Cache-Control" value="no-cache" />
        </customHeaders>
      </httpProtocol>
    </system.webServer>
  </location>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.