เซสชันและความปลอดภัย
เซสชันเอกสารและการควบคุมการเข้าถึง
โทเค็น Doconut ระบุเอกสารที่เปิดอยู่ หากมีคำขอใด ๆ ที่พาโทเค็นนี้ไปให้บริการ ผู้ที่ได้มามันจะสามารถอ่านทุกหน้าได้ หน้านี้อธิบายว่าเซสชันเอกสารเก็บอะไรไว้, อายุการใช้งานเท่าไหร่, และ DocImage.axd ตัดสินใจว่าใครสามารถดูหน้าของมันได้อย่างไร — ทั้งบนเซิร์ฟเวอร์เดียวและในฟาร์มเว็บ
สิ่งที่เซสชันเอกสารเก็บไว้
แต่ละการเรียก OpenDocumentAsync ที่สำเร็จจะสร้างเซสชันหนึ่งเซสชัน, เก็บไว้ในหน่วยความจำ:
- ตัวดูรูปแบบที่โหลดแล้ว — อินสแตนซ์เอนจินที่ถือเอกสารที่แปลงแล้ว,
- สถานะต่อหน้า — การหมุน, การพลิก, และข้อมูลคำอธิบายที่ผู้ใช้ใส่ในวิดเจ็ต,
- ดัชนีการค้นหา (ถ้ามี), สร้างขึ้นในการค้นหาครั้งแรก (หรือโหลดจากไฟล์
.srhที่สร้างไว้ล่วงหน้า), - ลายน้ำของเซสชัน จาก
DocOptions.Watermark.
อายุการใช้งาน
เซสชันหมดอายุตาม หน้าต่างเลื่อน: DocOptions.TimeOut นาที (ค่าเริ่มต้น 60) ซึ่งรีเซ็ตโดยทุกคำขอที่ส่งโทเค็นมา เมื่อเซสชันสิ้นสุด — ไม่ว่าจะหมดอายุหรือโดย CloseDocument(token) — เอนจินเอกสารจะถูกปล่อยและหน่วยความจำจะถูกคืนทันที
// A short-lived session for a one-shot preview
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });คำขอที่ใช้โทเค็นที่หมดอายุจะได้รับภาพข้อผิดพลาดที่อ่านว่า Document session not found. Please re-open document. หน้าเพจต้องเปิดเอกสารใหม่เพื่อรับโทเค็นใหม่ บนเซิร์ฟเวอร์เดียว การรีไซเคิลพูลแอปพลิเคชันก็จะทำให้ทุกเซสชันสิ้นสุดเช่นกัน
หน้าเพจจะให้บริการเฉพาะกับเซสชันที่เปิดมันเท่านั้น
เมื่อ UnsafeMode = false — ค่าตั้งต้น — การเปิดเอกสารจะให้สิทธิ์เข้าถึง เซสชัน ASP.NET ของคำขอที่เปิดมัน โดยการเขียนรายการ secure-{token} ลงในเซสชันนั้น DocImage.axd ต้องการสถานะเซสชันเอง, และจะให้บริการหน้าต่าง ๆ ก็ต่อเมื่อเซสชันที่ร้องขอมีรายการนั้นอยู่ คำขอจากเบราว์เซอร์อื่นที่นำโทเค็นเดียวกันมา จะได้รับภาพข้อผิดพลาดที่อ่านว่า You Are Not Authorized To View This Page.
Doconut.DoconutHost.Initialize(options =>
{
// false (the default): DocImage.axd serves a page only to the ASP.NET session that opened
// the document. The handler asks for session state itself; it only needs the site not to
// turn session state off in Web.config.
options.UnsafeMode = false;
});ผลที่ตามมาจากการทำงานจริงสามประการ:
- จุดเปิดต้องการสถานะเซสชัน คอนโทรลเลอร์ MVC และหน้า Web Forms มีโดยค่าเริ่มต้น
IHttpHandlerที่กำหนดเองจะไม่มีเว้นแต่จะทำการ implementSystem.Web.SessionState.IRequiresSessionStateเซสชันที่ไม่มีจะไม่มีสิ่งที่จะให้สิทธิ์, ดังนั้นผู้ดูจะโชว์ข้อความ “You Are Not Authorized To View This Page.” บนทุกหน้า - สถานะเซสชันต้องเปิดอยู่
<sessionState mode="Off" />ในWeb.configจะปิดการให้สิทธิ์และการตรวจสอบ, ทำให้ทุกหน้าโดนปฏิเสธ - เบราว์เซอร์ต้องส่งคุกกี้เซสชัน คำขอของวิดเจ็ตเป็น same‑origin จึงส่ง
ASP.NET_SessionIdอัตโนมัติ ลูกค้าที่ไม่มีคุกกี้ (สคริปต์, การเรียก server‑to‑server, การตั้งค่า cross‑origin ที่ตัดคุกกี้) จะถูกปฏิเสธ นี่คือคุณลักษณะที่ทำงานตามที่ออกแบบ
UnsafeMode = true ปิดการตรวจสอบ: คำขอใด ๆ ที่พาโทเค็นมาจะได้รับการให้บริการ นี่คือสวิตช์ระดับทั่วโลกสำหรับทุกเอกสาร, ไม่มีการตั้งค่าฉีดเฉพาะเอกสาร ปล่อยให้เป็น false
การเพิกถอน
CloseDocument(token) ทำมากกว่าการคืนหน่วยความจำ: มันลบรายการ secure-{token} จากเซสชันของคำขอปัจจุบันและเพิกถอนโทเค็น, ดังนั้นโทเค็นที่ปิดแล้วจะถูกปฏิเสธทันที
ฟาร์มเว็บ: ตั๋วที่ลงนาม
ในฟาร์ม, คำขอถัดไปอาจไปยังเซิร์ฟเวอร์ที่ไม่เคยเห็นเอกสาร, อยู่ในกระบวนการทำงานอื่น, มีเซสชัน ASP.NET ของตนเอง การให้สิทธิ์ผ่านเซสชันจึงไม่สามารถตามไปได้ โหมดกระจายจะแทนที่ด้วย ตั๋วที่ลงนาม ที่ผูกกับเบราว์เซอร์: ทุกโหนดแชร์ที่เก็บเซสชันเอกสารเดียวกันและคีย์การลงนามเดียวกัน, และ DocImage.axd จะยอมรับคำขอเมื่อตั๋วของมันถูกต้องสำหรับโทเค็นนั้น, เบราว์เซอร์นั้น, และ — เมื่อผู้ใช้เข้าสู่ระบบ — ผู้ใช้นั้น
การตั้งค่าที่เหมือนกันบนทุกโหนด:
// Global.asax.cs - Application_Start
Doconut.DoconutHost.Initialize(
options => options.UnsafeMode = false, // the ticket check only runs when this is false
services => services.AddDoconutDistributed(d =>
{
d.Store = CloudLocation.FileShare;
d.FileShareRootPath = @"\\fileserver\doconut-shared"; // a folder every node can reach
d.SigningKey = farmKey; // at least 32 bytes, the SAME on every node
}));จุดเปิดจะผูกตั๋วกับเบราว์เซอร์ก่อนเปิด, แล้วส่งตั๋วพร้อมโทเค็นกลับ:
- ตั้งค่า
DocOptions.BrowserId = DoconutFarmBinding.EnsureBrowserId(System.Web.HttpContext.Current, securityOptions)— มันจะออกคุกกี้doconut-clientที่ตั๋วผูกไว้ — และDocOptions.UserId = DoconutFarmBinding.ResolveUserId(System.Web.HttpContext.Current); - หลัง
OpenDocumentAsync, ส่งคืนviewer.AccessTokenควบคู่กับโทเค็น; - ในหน้า, ส่งทั้งสองค่าให้วิดเจ็ต:
objViewer.View(token, access).
Doconut.MvcSample.WebFarm ในแพ็กเกจตัวอย่างเป็นโหนดฟาร์มที่สมบูรณ์และสามารถรันได้, และคู่มือการย้ายที่อยู่ข้าง ๆ อธิบายขั้นตอนแต่ละอย่าง
เก็บคีย์การลงนามไว้นอกระบบควบคุมเวอร์ชัน: คีย์นี้ใช้ทั้งในการลงนามตั๋วและการเข้ารหัสเอกสารในที่เก็บร่วม โหนดที่ใช้คีย์ต่างกันจะปฏิเสธทุกตั๋วที่โหนดอื่นออก
ทดสอบฟาร์มด้วยเบราว์เซอร์จริง, หรือสคริปต์ที่เก็บคุกกี้ ลูกค้าที่ไม่มีคุกกี้ doconut-client จะไม่ได้รับการตอบกลับด้วย 401: จะได้รับภาพข้อผิดพลาด “not authorized” พร้อมสถานะ 200, ขนาดประมาณ 2 KB, ในขณะที่หน้าจริงมีขนาดหลายสิบถึงหลายร้อยกิโลไบต์
รายการตรวจสอบสำหรับการผลิต
- รักษา
UnsafeMode = false(ค่าเริ่มต้น) - เปิดเอกสารจากคำขอที่มีสถานะเซสชัน, และอย่าปิดสถานะเซสชัน
- ตรวจสอบให้คุกกี้เซสชันถึง
DocImage.axd(same origin, HTTPS, นโยบายSameSiteที่อนุญาต) - ในฟาร์ม, ใช้โหมดกระจายพร้อมคีย์การลงนามเดียวที่แชร์ระหว่างทุกโหนด
- เรียก
CloseDocumentเมื่อผู้ใช้ออกจากเอกสาร — ทั้งหน่วยความจำและความปลอดภัยจะได้ประโยชน์ - อย่าเก็บบันทึกหรือแชร์โทเค็น; ถือว่าเป็นข้อมูลประจำตัวที่มีอายุสั้น
หน้านี้เป็นประโยชน์หรือไม่?