在 Azure AI 搜尋中修剪結果的安全性篩選

Azure AI 搜尋不會提供檔層級許可權,而且無法依據用戶許可權,從相同的索引內變更搜尋結果。 因應措施是,您可以建立篩選條件,根據包含群組或使用者身分識別的字元串來修剪搜尋結果。

本文說明安全性篩選的模式,其中包含下列步驟:

  • 使用必要內容組合源檔
  • 建立主體標識碼的欄位
  • 將檔推送至搜尋索引以編製索引
  • 使用 search.in 篩選函式查詢索引

關於安全性篩選模式

雖然 Azure AI 搜尋服務並未與安全性子系統整合,以存取索引內的內容,但許多具有檔層級安全性需求的客戶發現篩選條件符合其需求。

在 Azure AI 搜尋服務中,安全性篩選條件是一般 OData 篩選條件,其包含或排除以比對值為基礎的搜尋結果,除了在安全性篩選中,準則是包含安全性主體的字串。 沒有透過安全性主體的驗證或授權。 主體只是用於篩選表達式中的字串,用來包含或排除搜尋結果中的檔。

有數種方式可以達成安全性篩選。 其中一種方式是透過複雜的相等表達式分離:例如、 Id eq 'id1' or Id eq 'id2'等等。 這種方法容易出錯、難以維護,而且如果清單包含數百或數千個值,則會讓查詢回應時間變慢數秒。

較佳的解決方案是針對安全性篩選使用 函 search.in 式,如本文所述。 如果您使用 search.in(Id, 'id1, id2, ...') 而不是相等表示式,您可以預期子秒的響應時間。

必要條件

  • 包含群組或使用者身分識別的字段必須是具有可篩選屬性的字串。 它應該是集合。 它不應該允許 Null。

  • 相同檔中的其他欄位應該提供該群組或用戶可存取的內容。 在下列 JSON 檔中,[security_id] 欄位包含安全性篩選中使用的身分識別,而且如果呼叫者的身分識別符合檔的“security_id”,則會包含名稱、工資和婚姻狀態。

    {  
        "Employee-1": {  
            "id": "100-1000-10-1-10000-1",
            "name": "Abram",   
            "salary": 75000,   
            "married": true,
            "security_id": "10011"
        },
        "Employee-2": {  
            "id": "200-2000-20-2-20000-2",
            "name": "Adams",   
            "salary": 75000,   
            "married": true,
            "security_id": "20022"
        } 
    }  
    

    注意

    本文並未涵蓋擷取主體標識碼,並將這些字串插入可編製 Azure AI 搜尋索引的來源檔中的程式。 如需取得標識符的說明,請參閱識別服務提供者的檔。

建立安全性欄位

在搜尋索引的欄位集合中,您需要一個包含群組或使用者身分識別的欄位,類似於上一個範例中的虛構 「security_id」字段。

  1. 將安全性欄位新增為 Collection(Edm.String)。 請確定其屬性 filterable 已設定為 true ,以便根據用戶擁有的存取權來篩選搜尋結果。 例如,如果您將 group_ids 「secured_file_b」 的檔file_name欄位設定為 ["group_id1, group_id2"] ,則只有屬於群組識別碼 「group_id1」 或 「group_id2」 的使用者具有檔案的讀取許可權。

    將欄位的 retrievable 屬性設定為 false ,使其不會在搜尋要求中傳回。

  2. 索引需要檔索引鍵。 “file_id” 欄位符合該需求。 索引也應該包含可搜尋的內容。 “file_name” 和 “file_description” 欄位代表在此範例中。

    POST https://[search service].search.windows.net/indexes/securedfiles/docs/index?api-version=2023-11-01
    {
         "name": "securedfiles",  
         "fields": [
             {"name": "file_id", "type": "Edm.String", "key": true, "searchable": false },
             {"name": "file_name", "type": "Edm.String", "searchable": true },
             {"name": "file_description", "type": "Edm.String", "searchable": true },
             {"name": "group_ids", "type": "Collection(Edm.String)", "filterable": true, "retrievable": false }
         ]
     }
    

使用 REST API 將數據推送至您的索引

將 HTTP POST 要求傳送至索引 URL 端點的檔集合(請參閱 檔 - 索引)。 HTTP 要求的本文是要編制索引之檔的 JSON 轉譯:

POST https://[search service].search.windows.net/indexes/securedfiles/docs/index?api-version=2023-11-01

在要求本文中,指定文件的內容:

{
    "value": [
        {
            "@search.action": "upload",
            "file_id": "1",
            "file_name": "secured_file_a",
            "file_description": "File access is restricted to the Human Resources.",
            "group_ids": ["group_id1"]
        },
        {
            "@search.action": "upload",
            "file_id": "2",
            "file_name": "secured_file_b",
            "file_description": "File access is restricted to Human Resources and Recruiting.",
            "group_ids": ["group_id1", "group_id2"]
        },
        {
            "@search.action": "upload",
            "file_id": "3",
            "file_name": "secured_file_c",
            "file_description": "File access is restricted to Operations and Logistics.",
            "group_ids": ["group_id5", "group_id6"]
        }
    ]
}

如果您需要使用群組清單更新現有的檔案,您可以使用 mergemergeOrUpload 動作:

{
    "value": [
        {
            "@search.action": "mergeOrUpload",
            "file_id": "3",
            "group_ids": ["group_id7", "group_id8", "group_id9"]
        }
    ]
}

在查詢中套用安全性篩選

若要根據 group_ids 存取權修剪檔,您應該使用篩選條件發出搜尋查詢 group_ids/any(g:search.in(g, 'group_id1, group_id2,...')) ,其中 'group_id1,group_id2,...'是搜尋要求簽發者所屬的群組。

此篩選會比對欄位包含其中一個指定識別碼的所有檔 group_ids 。 如需使用 Azure AI 搜尋來搜尋檔的完整詳細數據,您可以閱讀 搜尋檔

此範例示範如何使用POST要求來設定查詢。

發出 HTTP POST 要求:

POST https://[service name].search.windows.net/indexes/securedfiles/docs/search?api-version=2020-06-30
Content-Type: application/json  
api-key: [admin or query key]

在要求本文中指定篩選:

{
   "filter":"group_ids/any(g:search.in(g, 'group_id1, group_id2'))"  
}

您應該將檔案傳回 group_ids 包含 「group_id1」 或 「group_id2」。 換句話說,您會取得要求簽發者具有讀取許可權的檔。

{
 [
   {
    "@search.score":1.0,
     "file_id":"1",
     "file_name":"secured_file_a",
   },
   {
     "@search.score":1.0,
     "file_id":"2",
     "file_name":"secured_file_b"
   }
 ]
}

下一步

本文說明根據使用者身分識別和函式篩選結果的 search.in() 模式。 您可以使用此函式來傳入要求使用者的主體識別碼,以符合與每個目標文件相關聯的主體標識碼。 處理搜尋要求時,函 search.in 式會篩選出用戶主體沒有讀取許可權的搜尋結果。 主體標識碼可以代表安全組、角色,甚至是使用者自己的身分識別等專案。

如需以 Microsoft Entra ID 為基礎的替代模式,或重新流覽其他安全性功能,請參閱下列連結。