เซสชันและความปลอดภัย

เซสชันของเอกสารและการควบคุมการเข้าถึง

โทเคน Doconut มีพลังมาก: ผู้ที่นำเสนอมันสามารถร้องขอทุกหน้าของเอกสารได้หากไม่ได้ผูกกับเซสชันที่เปิดเอกสาร หน้านี้อธิบายว่าเซสชันเก็บอะไรบ้าง, อายุการใช้งานเป็นเท่าใด, และการตรวจสอบที่ UseDoconut() เปิดใช้งานโดยค่าเริ่มต้น.

สิ่งที่เซสชันของเอกสารเก็บไว้

แต่ละการเรียก OpenDocumentAsync ที่สำเร็จจะสร้างเซสชันหนึ่งใน IMemoryCache:

  • ตัวแสดงรูปแบบที่โหลดแล้ว (อินสแตนซ์เอนจินเอกสารที่ถือเอกสารที่แปลงแล้ว),
  • สถานะต่อหน้า — การหมุน, การพลิก, และข้อมูลคำอธิบายที่ผู้ใช้ใส่ในวิดเจ็ต,
  • ดัชนีการค้นหาแบบเลือกใช้ สร้างแบบ lazy เมื่อทำการค้นหาครั้งแรก (หรือโหลดจากไฟล์ .srh ที่สร้างไว้ล่วงหน้าเมื่อหน้าถูกเสิร์ฟจากที่เก็บข้อมูลร่วม),
  • ลายน้ำของเซสชัน จาก DocOptions.Watermark.

อายุการใช้งาน

เซสชันหมดอายุบน sliding window: DocOptions.TimeOut นาที (ค่าเริ่มต้น 60) ซึ่งจะรีเซ็ตโดยทุกคำขอที่นำเสนอโทเคน เมื่อเซสชันถูกไล่ออก — ด้วยการหมดอายุหรือโดย CloseDocument(token) — คอลแบ็กการไล่ออกจะทำลายเอนจินเอกสารและปล่อยหน่วยความจำที่เกี่ยวข้องทันที.

csharp
// เซสชันสั้น ๆ สำหรับการพรีวิวครั้งเดียว
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

คำขอที่ใช้โทเคนหมดอายุจะได้รับภาพข้อผิดพลาดที่แสดงข้อความ Document session not found. Please re-open document. — ลูกค้าต้องเปิดเอกสารใหม่เพื่อรับโทเคนใหม่.

การผูกโทเคนในตัว

เมื่อ UnsafeMode = false (ค่าเริ่มต้น), OpenDocumentAsync จะผูกโทเคนใหม่กับ ASP.NET session ของคำขอ HTTP ที่เปิดมันโดยเขียนมาร์กเกอร์ secure-{token} ลงในเซสชันนั้น. Middleware ของ Doconut จะปฏิเสธการให้บริการหน้าแก่เซสชันของเบราว์เซอร์อื่น:

  • เบราว์เซอร์/เซสชันที่ต่างกันนำเสนอโทเคนที่ถูกขโมย → ภาพข้อผิดพลาด You Are Not Authorized To View This Page.
  • Middleware ของเซสชันไม่ได้ลงทะเบียน → HTTP 500 Session middleware not configured. Call UseSession() before UseDoconut().

นี่คือเหตุผลที่ Quick Start ย้ำให้ใช้ AddSession() + app.UseSession() ก่อนสาขา Doconut. ผลลัพธ์เชิงปฏิบัติสองประการ:

  • ลูกค้าต้องส่ง คุกกี้เซสชันของ ASP.NET พร้อมกับคำขอหน้า การตั้งค่าข้ามต้นทางที่ลบคุกกี้ (หรือไคลเอนต์ API ที่ไม่มี cookie jar) จะทำให้การตรวจสอบล้มเหลว — นั่นคือการทำงานตามฟีเจอร์ ไม่ใช่บั๊ก
  • options.UnsafeMode = true ปิดการผูกโทเคนทั้งหมด มีไว้สำหรับสถานการณ์ที่ควบคุมได้; ควรตั้งเป็น false ในการผลิตบนโหนดเดียว

ไลบรารี .NET Standard รุ่นก่อนใช้ชื่อ property นี้ว่า UnSafeMode และส่งต่อไปยัง middleware; ที่นี่ใช้ชื่อ UnsafeMode และตั้งค่าเพียงครั้งเดียวภายใน AddDoconut().

การผูกโทเคนถูกควบคุมโดยสวิตช์ทั่วโลก UnsafeMode นี้เท่านั้น — มันเปิดโดยค่าเริ่มต้น (UnsafeMode = false) และใช้กับทุกเซสชัน ไม่มีการยกเว้นต่อเอกสารแต่ละไฟล์; การตั้งค่า UnsafeMode = true จะปิดการผูกโทเคนทั่วทั้งระบบ.

การให้สิทธิ์เข้าถึงและผู้ใช้ที่ผ่านการรับรอง

เมื่อ UnsafeMode เป็น false, UseDoconut() จะใส่ middleware การเข้าถึงเอกสารโดยอัตโนมัติก่อน middleware ของหน้า อย่าลงทะเบียนซ้ำ. เมื่อคำขอมีโทเคน, มันจะค้นหา access grant ที่บันทึกขณะเปิดเอกสารและให้สิทธิ์เฉพาะเมื่อเงื่อนไขต่อไปนี้เป็นจริง:

  1. มีการให้สิทธิ์สำหรับโทเคน
  2. ยังไม่หมดอายุ (อายุการให้สิทธิ์เท่ากับ TimeOut ของเอกสาร)
  3. ID ของ ASP.NET session ที่ร้องขอ ตรงกับเซสชันที่เปิดเอกสาร
  4. หากผู้เปิดผ่านการรับรอง, claim NameIdentifier ของผู้ใช้ที่ร้องขอตรงกันด้วย

การล้มเหลวจะคืนค่า 403 — เป็นภาพ PNG ข้อผิดพลาดสำหรับคำขอหน้า/ภาพย่อ, หรือเป็นข้อความธรรมดาในกรณีอื่น ข้อความและคีย์ query ของโทเคนมาจาก DocumentSecurityOptions (TokenQueryKey ค่าเริ่มต้น "token"; UnauthorizedMessage ค่าเริ่มต้น "You Are Not Authorized To View This Page.") ตั้งค่าตัวเลือกเหล่านี้ผ่าน ASP.NET Core DI ก่อนสร้างแอป หากสถานะเซสชันไม่พร้อมใช้งาน middleware จะปิดการทำงานด้วย HTTP 500: ASP.NET Session is required for Doconut document security.

csharp
builder.Services.Configure<Doconut.Security.DocumentSecurityOptions>(options =>
{
    options.TokenQueryKey = "token";
    options.UnauthorizedMessage = "You Are Not Authorized To View This Page.";
});

Middleware ของหน้าหลักจะตรวจสอบมาร์กเกอร์เซสชัน secure-{token} ก่อนให้บริการเอกสาร หาก UnsafeMode = true, UseDoconut() จะข้าม middleware การเข้าถึงและการตรวจสอบมาร์กเกอร์หลักก็จะถูกปิดด้วย.

ความปลอดภัยข้ามหลายโหนด

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

วิธีแกคือไม่ปล่อยเอกสารโดยไม่มีการป้องกัน ใช้ ticket การเข้าถึงที่ลงลายเซ็นผ่าน AddDoconutDistributedDocumentSecurity(...) ซึ่งแทนที่การตรวจสอบเซสชันด้วยข้อมูลรับรองที่แต่ละโหนดสามารถตรวจสอบได้อย่างอิสระ การจัดการเต็มรูปแบบอยู่ใน การปรับใช้แบบกระจาย.

การเพิกถอน

CloseDocument(token) ไม่ได้เพียงแค่ปล่อยหน่วยความจำ — มันยังลบมาร์กเกอร์ secure-{token} และเพิกถอนการให้สิทธิ์เข้าถึง ทำให้โทเคนที่ปิดใช้งานตายทั้งสองชั้นความปลอดภัยทันที

รายการตรวจสอบสำหรับการผลิต

  • รักษา UnsafeMode = false (ค่าเริ่มต้น) บนโหนดเดียว — สวิตช์ทั่วโลกนี้เป็นตัวผูกโทเคนกับเซสชัน
  • ลงทะเบียน AddDistributedMemoryCache() (แอป MVC และ Razor Pages มีอยู่แล้ว) และ AddSession(), แล้วเรียก app.UseSession() ก่อนสาขา middleware ของ Doconut
  • ตรวจสอบให้แน่ใจว่า policy ของคุกกี้เซสชันอนุญาตให้วิดเจ็ตส่งคุกกี้พร้อมคำขอ (SameSite, HTTPS)
  • ใช้ CloseDocument เมื่อผู้ใช้ออกจากเอกสาร — ทั้งหน่วยความจำและความปลอดภัยจะได้ประโยชน์
  • อย่าเก็บบันทึกหรือแชร์โทเคน; ปฏิบัติเช่นเป็นข้อมูลรับรองที่มีอายุสั้น
  • ให้บริการจากที่เก็บข้อมูลร่วม? ย้ายไปใช้ ticket การเข้าถึงที่ลงลายเซ็นแทนการรับเอกสารที่ไม่มีการป้องกัน.

หน้านี้เป็นประโยชน์หรือไม่?