Thiết kế tìm kiếm toàn cục nhận biết quyền mà không rò rỉ dữ liệu
Tìm hiểu cách thiết kế tìm kiếm toàn cục nhận biết quyền với chỉ mục nhanh và kiểm tra quyền trên từng bản ghi, để người dùng có kết quả nhanh mà không xảy ra rò rỉ.

Tại sao tìm kiếm toàn cục có thể rò rỉ dữ liệu
Tìm kiếm toàn cục thường là một ô tìm kiếm duy nhất quét toàn bộ ứng dụng: khách hàng, ticket, hóa đơn, tài liệu, người dùng và những thứ khác. Nó thường cấp gợi ý tự động và một trang kết quả nhanh để người dùng có thể nhảy trực tiếp tới một bản ghi.
Rò rỉ xảy ra khi tìm kiếm trả về thứ mà người dùng không được phép biết tồn tại. Ngay cả khi họ không thể mở bản ghi, một dòng như tiêu đề, tên người, thẻ hoặc đoạn trích được đánh dấu cũng có thể tiết lộ thông tin nhạy cảm.
Mọi người thường xem tìm kiếm là "chỉ đọc", nên các nhóm đánh giá thấp rủi ro. Nhưng nó có thể tiết lộ dữ liệu qua tiêu đề kết quả, bản xem trước, gợi ý autocomplete, tổng số kết quả, các facet như "Customers (5)", và thậm chí qua sự khác biệt về thời gian (nhanh với một số thuật ngữ, chậm với thuật ngữ khác).
Vấn đề này thường xuất hiện sau khi sản phẩm đã phát triển, không phải ngay ngày đầu. Ban đầu đội hay triển khai khi chỉ có một vai trò, hoặc mọi người đều thấy mọi thứ trong cơ sở dữ liệu thử nghiệm. Khi sản phẩm lớn lên, bạn thêm vai trò (support vs sales, managers vs agents) và tính năng như hộp thư chia sẻ, ghi chú riêng tư, khách hàng bị hạn chế, và "chỉ tài khoản của tôi." Nếu tìm kiếm vẫn dựa trên giả định cũ, nó sẽ bắt đầu trả về gợi ý chéo giữa các nhóm hoặc khách hàng.
Một lỗi phổ biến là lập chỉ mục "mọi thứ" để có tốc độ, rồi cố lọc kết quả trong ứng dụng sau khi truy vấn. Lúc đó đã quá muộn. Công cụ tìm kiếm đã quyết định cái gì khớp, và nó có thể phơi bày các bản ghi bị hạn chế qua gợi ý, số đếm, hoặc các trường hiển thị một phần.
Hãy tưởng tượng một agent hỗ trợ chỉ được xem ticket của khách hàng được phân công cho họ. Họ gõ "Acme" và autocomplete hiển thị "Acme - Legal escalation" hoặc "Acme breach notification." Ngay cả khi nhấp vào bị trả về "access denied", tiêu đề đó vẫn là một rò rỉ dữ liệu.
Mục tiêu của tìm kiếm toàn cục nhận biết quyền nghe thì đơn giản nhưng khó triển khai: trả về kết quả nhanh và phù hợp đồng thời thực thi cùng quy tắc truy cập bạn áp dụng khi mở mỗi bản ghi. Mỗi truy vấn phải hành xử như thể người dùng chỉ được thấy lát dữ liệu của họ, và UI phải tránh rò rỉ manh mối (như số đếm) ngoài lát đó.
Những gì bạn đang lập chỉ mục và những gì phải bảo vệ
Tìm kiếm toàn cục có vẻ đơn giản vì người dùng gõ từ và mong nhận câu trả lời. Nhưng bên trong, bạn đang tạo một bề mặt mới để lộ dữ liệu. Trước khi chọn chỉ mục hoặc tính năng DB, hãy rõ hai điều: những đối tượng bạn tìm kiếm (entity), và những phần của đối tượng đó là nhạy cảm.
Entity là bất kỳ bản ghi ai đó muốn tìm nhanh: khách hàng, ticket hỗ trợ, hóa đơn, đơn hàng, và file (hoặc metadata file). Cũng có thể bao gồm hồ sơ con người (người dùng, agent), ghi chú nội bộ, và đối tượng hệ thống như integration hoặc API key. Nếu nó có tên, ID, hoặc trạng thái mà ai đó có thể gõ, nó thường kết thúc trong tìm kiếm toàn cục.
Quy tắc theo bản ghi so với theo bảng
Quy tắc theo bảng là thô: hoặc bạn truy cập toàn bộ bảng, hoặc không. Ví dụ: chỉ Finance có thể mở trang Invoices. Dễ hiểu nhưng vỡ vụn khi những người khác nhau nên thấy các hàng khác nhau cùng trong một bảng.
Quy tắc theo bản ghi quyết định hiển thị từng hàng một. Ví dụ: một agent support thấy ticket được phân cho team của họ, trong khi quản lý thấy tất cả ticket trong vùng của họ. Một quy tắc phổ biến khác là ownership theo tenant: trong app đa-tenant, người dùng chỉ thấy các bản ghi nơi customer_id = their_customer_id.
Chính những quy tắc theo bản ghi này thường khiến tìm kiếm rò rỉ. Nếu chỉ mục trả về kết quả trước khi bạn kiểm tra quyền hàng, bạn đã tiết lộ rằng thứ gì đó tồn tại.
"Được phép xem" nghĩa là gì trong thực tế
"Được phép" hiếm khi là một công tắc đơn/nhị phân. Nó thường kết hợp ownership (tạo bởi tôi, phân công cho tôi), membership (team của tôi, phòng ban, vai trò), phạm vi (vùng, đơn vị kinh doanh, dự án), trạng thái bản ghi (published, không lưu trữ), và các trường hợp đặc biệt (khách VIP, lệnh pháp lý, thẻ bị hạn chế).
Hãy viết những quy tắc này ra bằng ngôn ngữ đơn giản trước. Sau đó bạn sẽ biến chúng thành mô hình dữ liệu cộng với kiểm tra phía máy chủ.
Quyết định những gì an toàn để hiển thị trong preview kết quả
Kết quả tìm kiếm thường bao gồm snippet xem trước, và snippet có thể làm lộ dữ liệu ngay cả khi người dùng không thể mở bản ghi.
Một mặc định an toàn là chỉ hiển thị các trường tối thiểu, không nhạy cảm cho đến khi quyền được xác nhận: tên hiển thị hoặc tiêu đề (thỉnh thoảng che bớt), mã định danh ngắn (như số đơn hàng), trạng thái tổng quan (Open, Paid, Shipped), ngày (tạo hoặc cập nhật), và một nhãn đối tượng chung (Ticket, Invoice).
Ví dụ cụ thể: nếu ai đó tìm "Acme merger" và có ticket bị hạn chế, trả về "Ticket: Acme merger draft - Legal" đã là rò rỉ. An toàn hơn là "Ticket: Restricted" không có snippet, hoặc không trả về gì, tùy chính sách của bạn.
Định nghĩa đúng ngay từ đầu sẽ làm các quyết định sau này đơn giản hơn: bạn lập chỉ mục cái gì, lọc thế nào, và sẵn sàng tiết lộ tới mức nào.
Yêu cầu cơ bản để tìm kiếm an toàn và nhanh
Mọi người dùng tìm kiếm toàn cục khi họ vội. Nếu mất hơn một giây, họ sẽ mất niềm tin và quay về lọc thủ công. Nhưng tốc độ chỉ là một nửa. Một tìm kiếm nhanh mà làm lộ dù chỉ một tiêu đề, tên khách hàng, hoặc chủ đề ticket còn tệ hơn không có tìm kiếm.
Quy tắc lõi không thương lượng: thực thi quyền tại thời điểm truy vấn, không chỉ ở UI. Ẩn một hàng sau khi đã fetch đã là quá muộn, vì hệ thống đã chạm tới dữ liệu lẽ ra không nên trả về.
Điều này áp dụng cho mọi thứ xung quanh tìm kiếm, không chỉ danh sách kết quả cuối cùng. Gợi ý, top hits, số đếm, và thậm chí trạng thái "không có kết quả" đều có thể rò rỉ thông tin. Autocomplete hiện "Acme Renewal Contract" cho người không được mở nó là rò rỉ. Một facet báo "12 hóa đơn trùng khớp" là rò rỉ nếu người dùng chỉ được thấy 3. Thời gian phản hồi cũng có thể làm lộ nếu các kết quả bị hạn chế làm truy vấn chậm đi.
Một tìm kiếm toàn cục an toàn cần bốn điều:
- Đúng: mọi mục trả về đều được phép cho người dùng này, tenant này, vào thời điểm này.
- Nhanh: kết quả, gợi ý và số đếm giữ tốc độ nhất quán, ngay cả ở quy mô lớn.
- Nhất quán: khi quyền thay đổi (cập nhật vai trò, ticket được giao lại), hành vi tìm kiếm thay đổi nhanh và dự đoán được.
- Có thể kiểm toán: bạn có thể giải thích vì sao một mục được trả về, và ghi nhật ký hoạt động tìm kiếm để điều tra.
Một thay đổi tư duy hữu ích: xem tìm kiếm như một API dữ liệu, không chỉ là tính năng UI. Điều đó nghĩa là cùng quy tắc truy cập bạn áp dụng cho trang danh sách cũng phải áp dụng cho việc xây dựng chỉ mục, thực thi truy vấn, và mọi endpoint liên quan (autocomplete, tìm kiếm gần đây, truy vấn phổ biến).
Ba mẫu thiết kế phổ biến (và khi nào dùng chúng)
Một ô tìm kiếm dễ xây. Tìm kiếm toàn cục nhận biết quyền khó hơn vì chỉ mục muốn trả kết quả tức thì, trong khi app của bạn không bao giờ được tiết lộ bản ghi người dùng không có quyền, kể cả gián tiếp.
Dưới đây là ba mẫu bạn hay gặp. Lựa chọn phụ thuộc độ phức tạp của quy tắc truy cập và mức rủi ro bạn chấp nhận.
Cách A: chỉ lập chỉ mục các trường "an toàn", rồi fetch sau khi kiểm tra quyền. Bạn lưu một document tối thiểu trong chỉ mục, như ID cộng một nhãn không nhạy cảm an toàn để mọi người dùng thấy. Khi người dùng nhấp kết quả, app tải bản ghi đầy đủ từ DB chính và áp dụng quy tắc quyền thực sự ở đó.
Cách này giảm rủi ro rò rỉ, nhưng kết quả có thể hơi ít thông tin vì người dùng nhận ít ngữ cảnh. Cần chú ý tới cách diễn giải UI để nhãn "an toàn" không vô tình tiết lộ bí mật.
Cách B: lưu thuộc tính quyền trong chỉ mục và lọc ở đó. Bạn thêm các trường như tenant_id, team_id, owner_id, cờ vai trò, hoặc project_id trong mỗi document. Mỗi truy vấn thêm bộ lọc phù hợp với phạm vi người dùng hiện tại.
Cách này cho kết quả phong phú, autocomplete nhanh, nhưng chỉ áp dụng khi quyền có thể biểu diễn bằng bộ lọc. Nếu quyền phụ thuộc logic phức tạp (ví dụ, "được phân công HOẶC trực tuần này HOẶC tham gia incident"), khó giữ đúng.
Cách C: kết hợp. Lọc thô trong chỉ mục, kiểm tra cuối cùng ở DB. Bạn lọc trong chỉ mục bằng các thuộc tính ổn định, rộng (tenant, workspace, customer), rồi kiểm tra lại quyền trên tập ID nhỏ các ứng viên trong DB chính trước khi trả kết quả.
Đây thường là con đường an toàn cho app thực tế: chỉ mục vẫn nhanh, DB là nguồn chân lý.
Chọn mẫu
Chọn A khi bạn muốn cài đặt đơn giản và chấp nhận kết quả ít ngữ cảnh. Chọn B khi bạn có phạm vi rõ ràng, tĩnh (đa-tenant, truy cập theo team) và cần autocomplete rất nhanh. Chọn C khi bạn có nhiều vai trò, ngoại lệ, hoặc quy tắc theo bản ghi thay đổi thường xuyên. Với dữ liệu rủi ro cao (HR, tài chính, y tế), ưu tiên C vì "gần đúng" không chấp nhận được.
Từng bước: thiết kế chỉ mục tôn trọng quy tắc truy cập
Bắt đầu bằng việc viết quy tắc truy cập như bạn giải thích cho một đồng nghiệp mới. Tránh "admin thấy mọi thứ" trừ khi thật sự đúng. Hãy diễn đạt nguyên nhân: "Support agents thấy ticket từ tenant của họ. Team leads thấy thêm ticket từ unit của họ. Chỉ owner và agent được phân công xem private notes." Nếu bạn không thể nói vì sao ai đó được thấy bản ghi, bạn sẽ gặp khó khi mã hóa an toàn.
Tiếp theo, chọn một định danh ổn định và định nghĩa document tìm kiếm tối thiểu. Chỉ mục không nên là bản sao đầy đủ của hàng DB. Giữ chỉ những gì cần để tìm và hiển thị trong danh sách kết quả, như tiêu đề, trạng thái, và có thể một snippet ngắn không nhạy cảm. Đặt các trường nhạy cảm sau một lần fetch thứ hai kèm kiểm tra quyền.
Rồi quyết định các tín hiệu quyền bạn có thể lọc nhanh. Đây là các thuộc tính khoá có thể lưu trong mỗi document, như tenant_id, org_unit_id, và vài cờ phạm vi. Mục tiêu là mỗi truy vấn có thể áp dụng bộ lọc trước khi trả kết quả, kể cả autocomplete.
Một workflow thực tế:
- Định nghĩa quy tắc hiển thị cho mỗi entity bằng ngôn ngữ thường.
- Tạo schema document tìm kiếm với record_id và chỉ các trường an toàn, có thể tìm kiếm.
- Thêm các trường quyền có thể lọc (tenant_id, org_unit_id, visibility_level) vào mỗi document.
- Xử lý ngoại lệ bằng grant rõ ràng: lưu allowlist (ID người dùng) hoặc ID nhóm cho các mục chia sẻ.
Các mục chia sẻ và ngoại lệ là nơi hay bị vỡ. Nếu ticket có thể chia sẻ giữa team, đừng "chỉ thêm boolean." Dùng allowlist rõ ràng để lọc. Nếu allowlist lớn, ưu tiên grant theo nhóm thay vì cá nhân.
Giữ chỉ mục đồng bộ mà không có bất ngờ
Trải nghiệm tìm kiếm an toàn phụ thuộc vào một việc nhàm chán nhưng quan trọng: chỉ mục phải phản ánh thực tế. Nếu một bản ghi được tạo, thay đổi, xóa, hoặc quyền của nó đổi, kết quả tìm kiếm phải theo kịp nhanh và dự đoán được.
Theo dõi create, update, delete
Xem việc lập chỉ mục như một phần của vòng đời dữ liệu. Một mô hình tư duy hữu ích: mỗi khi nguồn chân lý thay đổi, bạn phát ra một event và indexer phản ứng.
Các cách phổ biến gồm trigger DB, event từ ứng dụng, hoặc hàng đợi công việc. Quan trọng nhất là event không bị mất. Nếu app lưu bản ghi nhưng thất bại khi lập chỉ mục, bạn sẽ gặp hành vi khó hiểu như "Tôi biết nó tồn tại nhưng tìm kiếm không thấy."
Thay đổi quyền cũng là thay đổi chỉ mục
Nhiều rò rỉ xảy ra khi nội dung cập nhật đúng, nhưng metadata quyền thì không. Thay đổi quyền đến từ cập nhật vai trò, chuyển team, chuyển ownership, gán lại khách hàng, hoặc gộp ticket.
Hãy coi thay đổi quyền là event quan trọng. Nếu tìm kiếm phụ thuộc vào tenant hoặc bộ lọc team, đảm bảo document được chỉ mục chứa các trường cần thiết để thực thi điều đó (tenant_id, team_id, owner_id, allowed_role_ids). Khi các trường đó thay đổi, reindex.
Phần khó là phạm vi ảnh hưởng. Một thay đổi vai trò có thể ảnh hưởng hàng nghìn bản ghi. Hãy có đường dẫn reindex hàng loạt với tiến độ, retry và khả năng tạm dừng.
Lập kế hoạch cho eventual consistency
Ngay cả với event tốt, vẫn có cửa sổ trễ khi tìm kiếm đi sau. Quyết định người dùng nên thấy gì trong vài giây đầu sau thay đổi.
Hai quy tắc hữu ích:
- Nhất quán về độ trễ. Nếu lập chỉ mục thường hoàn tất trong 2–5 giây, đặt kỳ vọng đó nơi cần thiết.
- Thà thiếu còn hơn lộ. An toàn hơn khi một bản ghi mới được cấp quyền xuất hiện muộn hơn là một bản ghi bị thu hồi vẫn tiếp tục hiển thị.
Thêm fallback an toàn khi chỉ mục lỗi thời
Tìm kiếm để khám phá, nhưng xem chi tiết là nơi rò rỉ nguy hiểm. Hãy làm kiểm tra quyền thứ hai khi đọc để hiển nhiên trước khi hiển thị trường nhạy cảm. Nếu một kết quả lọt qua do chỉ mục lỗi thời, trang chi tiết vẫn phải chặn truy cập.
Một mẫu tốt: hiển thị snippet tối thiểu trong tìm kiếm, rồi kiểm tra lại quyền khi người dùng mở bản ghi (hoặc mở preview). Nếu kiểm tra thất bại, hiện thông báo rõ ràng và loại bỏ mục đó khỏi kết quả hiển thị ở lần làm mới sau.
Sai lầm phổ biến gây rò rỉ dữ liệu
Tìm kiếm có thể rò rỉ ngay cả khi trang "mở bản ghi" của bạn được khoá kỹ. Người dùng có thể không bao giờ nhấp kết quả mà vẫn biết tên, ID khách hàng, hoặc quy mô một project bị ẩn. Tìm kiếm toàn cục nhận biết quyền phải bảo vệ không chỉ tài liệu, mà cả manh mối về tài liệu.
Autocomplete là nguồn rò rỉ thường gặp. Gợi ý thường dùng lookup tiền tố nhanh bỏ qua kiểm tra quyền đầy đủ. UI trông vô hại, nhưng một ký tự gõ vào có thể tiết lộ tên khách hàng hoặc email nhân viên. Autocomplete phải chạy cùng bộ lọc truy cập như tìm kiếm đầy đủ, hoặc được xây dựng từ tập gợi ý đã lọc sẵn (ví dụ theo tenant và vai trò).
Số đếm facet và banner "About 1,243 results" là một rò rỉ thầm lặng khác. Số đếm có thể xác nhận sự tồn tại ngay cả khi bạn ẩn bản ghi. Nếu bạn không thể tính toán số đếm an toàn theo cùng quy tắc truy cập, hãy hiển thị ít chi tiết hơn hoặc bỏ số đếm.
Caching cũng là thủ phạm. Cache chia sẻ giữa người dùng, vai trò hoặc tenant có thể tạo "result ghosts", nơi một người thấy kết quả sinh cho người khác. Việc này xảy ra với edge cache, cache ứng dụng và cache trong bộ nhớ của dịch vụ tìm kiếm.
Các bẫy rò rỉ cần kiểm tra sớm:
- Autocomplete và tìm kiếm gần đây được lọc bởi cùng quy tắc như tìm kiếm đầy đủ.
- Số đếm facet và totals được tính sau khi áp quyền.
- Khóa cache bao gồm tenant ID và chữ ký quyền (vai trò, team, user ID).
- Logs và analytics không lưu truy vấn thô hoặc snippet kết quả cho dữ liệu bị hạn chế.
Cuối cùng, cảnh giác với bộ lọc quá rộng. "Lọc theo tenant" là lỗi kinh điển đa-tenant, nhưng điều tương tự xảy ra trong một tenant: lọc theo "department" khi truy cập là theo bản ghi. Ví dụ: một agent tìm "refund" và thấy kết quả khắp tenant, kể cả tài khoản VIP chỉ cho team nhỏ hơn. Sửa đơn giản: thực thi quy tắc hàng-cấp trong mọi đường dẫn truy vấn (tìm kiếm, autocomplete, facets, xuất khẩu), không chỉ ở trang xem bản ghi.
Chi tiết bảo mật và quyền riêng tư hay quên
Nhiều thiết kế tập trung vào "ai được thấy gì", nhưng rò rỉ còn xảy ra qua các cạnh: trạng thái rỗng, thời gian và manh mối nhỏ trong UI. Tìm kiếm nhận biết quyền phải an toàn ngay cả khi trả về không có gì.
Một rò rỉ dễ là xác nhận bằng vắng mặt. Nếu người không có quyền tìm một tên khách hàng, ID ticket, hoặc email và nhận được thông báo đặc biệt như "No access" hay "You don't have permission," bạn đã xác nhận bản ghi tồn tại. Hãy coi "không tìm thấy" như kết quả mặc định cho cả "không tồn tại" và "tồn tại nhưng không được phép." Giữ thời gian phản hồi và cách diễn đạt nhất quán để người ta không đoán dựa trên tốc độ.
Khớp một phần nhạy cảm
Autocomplete và search-as-you-type là nơi dễ lộ. Khớp một phần trên email, số điện thoại, số chứng minh có thể tiết lộ nhiều hơn bạn định. Quyết định trước cách các trường này hoạt động.
Một bộ quy tắc thực tế:
- Yêu cầu khớp chính xác cho các trường rủi ro cao (email, phone, ID).
- Tránh hiển thị snippet được đánh dấu làm lộ văn bản ẩn.
- Cân nhắc tắt autocomplete cho các trường nhạy cảm hoàn toàn.
Nếu hiển thị chỉ một ký tự cũng giúp ai đó đoán dữ liệu, coi đó là nhạy cảm.
Kiểm soát lạm dụng mà không tạo rủi ro mới
Endpoint tìm kiếm là mục tiêu hoàn hảo cho tấn công liệt kê: thử nhiều truy vấn để mapping cái gì tồn tại. Thêm giới hạn tốc độ và phát hiện bất thường, nhưng cẩn thận với những gì lưu lại. Logs có truy vấn thô có thể trở thành nguồn rò rỉ thứ hai.
Giữ đơn giản: rate limit theo user, theo IP, và theo tenant; log số lần, thời gian và mẫu thô (không lưu truy vấn đầy đủ); cảnh báo các truy vấn "gần trúng" liên tiếp (như ID liên tiếp); và chặn hoặc tăng mức xác thực sau nhiều lần thất bại.
Hãy làm lỗi của bạn trở nên nhàm chán. Dùng cùng một thông điệp và cùng trạng thái rỗng cho "không có kết quả", "không được phép" và "lọc không hợp lệ." UI càng ít nói, càng ít có khả năng vô tình tiết lộ.
Ví dụ: đội support tìm ticket qua nhiều khách hàng
Một agent support, Maya, làm việc cho team xử lý ba tài khoản khách hàng. Cô có một ô tìm kiếm ở tiêu đề app. Sản phẩm có chỉ mục toàn cục cho ticket, contact và company, nhưng mọi kết quả phải tuân theo quy tắc truy cập.
Maya gõ "Alic" vì caller nói tên Alice. Autocomplete hiển thị vài gợi ý. Cô nhấp "Alice Nguyen - Ticket: Password reset." Trước khi mở, app kiểm tra lại quyền cho bản ghi đó. Nếu ticket vẫn phân cho team của cô và vai trò cho phép, cô sẽ vào được ticket.
Maya thấy ở mỗi bước:
- Ô tìm kiếm: gợi ý hiện nhanh, nhưng chỉ cho những bản ghi cô có quyền truy cập ngay bây giờ.
- Danh sách kết quả: tiêu đề ticket, tên khách, thời gian cập nhật gần nhất. Không có placeholder "bạn không có quyền".
- Chi tiết ticket: view đầy đủ chỉ tải sau kiểm tra quyền phía server. Nếu quyền thay đổi, app hiện "Ticket not found" (không phải "forbidden").
Bây giờ so với Leo, một agent mới. Vai trò của cậu chỉ xem ticket đánh dấu "Public to Support" và chỉ cho một khách hàng. Leo gõ "Alic." Cậu thấy ít gợi ý hơn, và không có manh mối về những mục bị thiếu. Không có số "5 results" hé lộ có các kết quả khác. UI chỉ đơn giản hiển thị những gì cậu có thể mở.
Sau đó, một quản lý chuyển "Alice Nguyen - Password reset" từ team của Maya sang team chuyên trách. Trong một cửa sổ ngắn (thường vài giây đến vài phút, tùy cơ chế đồng bộ của bạn), tìm kiếm của Maya ngừng trả về ticket đó. Nếu cô đang mở trang chi tiết và làm mới, app kiểm tra lại quyền và ticket biến mất.
Đó là hành vi bạn muốn: gõ nhanh và kết quả nhanh, không để lại mùi dữ liệu qua số đếm, snippet, hay mục chỉ mục lỗi thời.
Checklist và bước tiếp theo để triển khai an toàn
Tìm kiếm toàn cục nhận biết quyền chỉ "xong" khi các cạnh nhàm chán cũng an toàn. Nhiều rò rỉ xảy ra ở chỗ tưởng vô hại: autocomplete, số đếm, và xuất khẩu.
Kiểm tra an toàn nhanh
Trước khi phát hành, chạy qua các kiểm tra này với dữ liệu thật, không phải sample:
- Autocomplete: không bao giờ gợi ý tiêu đề, tên hoặc ID mà người dùng không thể mở.
- Số đếm và facets: nếu hiển thị tổng hoặc số nhóm, tính sau khi áp quyền (hoặc bỏ số đếm).
- Xuất khẩu và hành động hàng loạt: xuất "tìm kiếm hiện tại" phải kiểm tra lại quyền từng hàng lúc xuất.
- Sắp xếp và highlight: không sắp/hightlight dùng trường người dùng không được thấy.
- "Không tìm thấy" vs "bị cấm": với entity nhạy cảm, cân nhắc cùng hình dạng phản hồi để người dùng không xác nhận tồn tại.
Kế hoạch kiểm thử bạn có thể chạy
Tạo ma trận vai trò nhỏ (vai trò x entity) và dataset có các trường hợp khó: bản ghi chia sẻ, quyền vừa bị thu hồi, và lookalike giữa tenant.
Thử theo ba bước: (1) kiểm tra ma trận vai trò: xác minh bản ghi bị từ chối không bao giờ xuất hiện trong kết quả, gợi ý, số đếm hoặc xuất khẩu; (2) thử "phá": dán ID, tìm theo email hoặc phone, thử khớp một phần mà lẽ ra không trả về gì; (3) kiểm tra thời gian và cache: thay đổi quyền và xác nhận kết quả cập nhật nhanh, không có gợi ý lỗi thời.
Về vận hành, chuẩn bị cho ngày kết quả tìm kiếm "trông sai." Ghi lại ngữ cảnh truy vấn (user, vai trò, tenant) và các bộ lọc quyền đã áp dụng, nhưng tránh lưu chuỗi truy vấn thô hoặc snippet nhạy cảm. Để debug an toàn, xây công cụ chỉ admin có thể dùng để giải thích vì sao một bản ghi khớp và vì sao nó được phép.
Nếu bạn xây trên AppMaster (appmaster.io), một cách thực tế là giữ tìm kiếm như luồng phía server: mô hình hóa entity và quan hệ trong Data Designer, thực thi quyền trong Business Processes, và tái sử dụng cùng kiểm tra quyền đó cho autocomplete, danh sách kết quả và xuất khẩu để chỉ có một nơi cần làm đúng.


