Phiên & Bảo mật

Phiên tài liệu và kiểm soát truy cập

Một token Doconut rất mạnh: bất kỳ ai trình bày nó đều có thể yêu cầu mọi trang của tài liệu nếu nó không được ràng buộc với phiên mở. Trang này giải thích những gì một phiên chứa, thời gian tồn tại của nó, và các kiểm tra mà UseDoconut() bật theo mặc định.

Những gì một phiên tài liệu chứa

Mỗi OpenDocumentAsync thành công tạo ra một phiên trong IMemoryCache:

  • trình xem định dạng đã tải (đối tượng engine tài liệu giữ tài liệu đã phân tích),
  • trạng thái mỗi trang — xoay, lật và dữ liệu chú thích mà người dùng áp dụng trong widget,
  • chỉ mục tìm kiếm tùy chọn, được xây dựng lười biếng khi tìm kiếm lần đầu (hoặc được tải từ tệp .srh đã được xây dựng trước khi các trang được phục vụ từ lưu trữ chung),
  • dấu watermark phiên từ DocOptions.Watermark.

Thời lượng

Các phiên hết hạn dựa trên sliding window: DocOptions.TimeOut phút (mặc định 60), được đặt lại bởi mỗi yêu cầu trình bày token. Khi một phiên bị loại bỏ — do hết hạn hoặc bởi CloseDocument(token) — callback loại bỏ sẽ giải phóng engine tài liệu và giải phóng bộ nhớ liên quan ngay lập tức.

csharp
// Một phiên ngắn hạn cho bản xem trước một lần
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

Một yêu cầu với token đã hết hạn sẽ nhận được hình ảnh lỗi hiển thị Document session not found. Please re-open document. — client phải mở lại để lấy token mới.

Ràng buộc token tích hợp

Với UnsafeMode = false (mặc định), OpenDocumentAsync ràng buộc token mới với phiên ASP.NET của yêu cầu HTTP đã mở nó, bằng cách ghi một dấu secure-{token} vào phiên đó. Middleware Doconut sau đó từ chối phục vụ các trang cho bất kỳ phiên trình duyệt nào khác:

  • Trình duyệt/phien khác trình bày token bị đánh cắp → hình ảnh lỗi You Are Not Authorized To View This Page.
  • Middleware phiên không được đăng ký → HTTP 500 Session middleware not configured. Call UseSession() before UseDoconut().

Đây là lý do tại sao Quick Start yêu cầu AddSession() + app.UseSession() trước nhánh Doconut. Hai hậu quả thực tiễn:

  • Client phải gửi cookie phiên ASP.NET cùng với các yêu cầu trang. Các cấu hình cross-origin mà loại bỏ cookie (hoặc client API không có cookie jar) sẽ không vượt qua kiểm tra — đó là tính năng hoạt động, không phải lỗi.
  • options.UnsafeMode = true vô hiệu hoá hoàn toàn việc ràng buộc. Nó tồn tại cho các kịch bản kiểm soát; để false trong môi trường production trên một node duy nhất.

Lưu ý cách viết. Thư viện .NET Standard trước đây gọi thuộc tính này là UnSafeMode và nó đã được truyền vào middleware; ở đây nó là UnsafeMode và được đặt một lần bên trong AddDoconut().

Ràng buộc token chỉ được điều khiển bởi công tắc toàn cục UnsafeMode này — nó bật theo mặc định (UnsafeMode = false) và áp dụng cho mọi phiên. Không có tùy chọn tắt theo tài liệu; việc đặt UnsafeMode = true sẽ vô hiệu hoá ràng buộc trên toàn bộ.

Quyền truy cập và người dùng đã xác thực

Khi UnsafeMode là false, UseDoconut() tự động chèn middleware truy cập tài liệu trước middleware trang. Không đăng ký lại lần thứ hai. Khi một yêu cầu mang token, nó tra cứu access grant đã ghi lại khi tài liệu được mở và chỉ cho phép nếu tất cả các điều kiện sau đều đúng:

  1. một grant tồn tại cho token,
  2. grant chưa hết hạn (thời gian grant = TimeOut của tài liệu),
  3. ID phiên ASP.NET yêu cầu khớp với ID đã mở tài liệu,
  4. nếu người mở đã xác thực, claim NameIdentifier của người dùng yêu cầu cũng phải khớp.

Các lỗi trả về 403 — dưới dạng hình ảnh PNG lỗi cho các yêu cầu trang/thumbnail, và dưới dạng văn bản thuần cho các trường hợp khác. Thông báo và khóa truy vấn token đến từ DocumentSecurityOptions (TokenQueryKey, mặc định "token"; UnauthorizedMessage, mặc định "You Are Not Authorized To View This Page."). Cấu hình các tùy chọn này qua ASP.NET Core DI trước khi xây dựng ứng dụng. Nếu trạng thái phiên không khả dụng, middleware sẽ đóng lại với 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 trang cốt lõi sau đó xác minh dấu secure-{token} của phiên trước khi phục vụ tài liệu. Với UnsafeMode = true, UseDoconut() bỏ qua middleware truy cập và việc kiểm tra dấu cốt lõi cũng bị vô hiệu hoá.

Bảo mật trên nhiều node

Token ràng buộc phiên giả định rằng node phục vụ một trang cũng đã thấy yêu cầu mở tài liệu. Giả định này không đúng khi nhiều node phục vụ cùng một tài liệu từ lưu trữ chung: một yêu cầu trang có thể đến một node chưa từng thấy yêu cầu mở, và kiểm tra per-session sẽ từ chối.

Câu trả lời không phải là để tài liệu không được bảo vệ. Sử dụng vé truy cập có chữ ký qua AddDoconutDistributedDocumentSecurity(...), thay thế kiểm tra phiên bằng một chứng chỉ mà mỗi node có thể xác minh độc lập. Sắp xếp đầy đủ được mô tả trong Triển khai phân tán.

Thu hồi

CloseDocument(token) không chỉ giải phóng bộ nhớ — nó còn loại bỏ dấu secure-{token} và thu hồi access grant, vì vậy một token đã đóng sẽ chết ngay trên cả hai lớp bảo mật.

Danh sách kiểm tra cho production

  • Giữ UnsafeMode = false (mặc định) trên một node duy nhất — công tắc toàn cục này là thứ ràng buộc token với các phiên.
  • Đăng ký AddDistributedMemoryCache() (các ứng dụng MVC và Razor Pages đã có) và AddSession(), và gọi app.UseSession() trước nhánh middleware Doconut.
  • Đảm bảo chính sách cookie phiên của bạn cho phép các yêu cầu của widget mang cookie (SameSite, HTTPS).
  • Sử dụng CloseDocument khi người dùng rời tài liệu — cả bộ nhớ và bảo mật đều được cải thiện.
  • Không bao giờ ghi log hoặc chia sẻ token; coi chúng như chứng chỉ ngắn hạn.
  • Phục vụ từ lưu trữ chung? Chuyển sang vé truy cập có chữ ký thay vì chấp nhận tài liệu không được bảo vệ.

Trang này có hữu ích không?