在 Azure Functions 中使用受控連接器

透過使用受管理連接器,你的函式可以對 Microsoft 365、Microsoft Teams、SharePoint 及許多第三方系統中的事件和呼叫操作做出反應,而無需撰寫 webhook 設定程式碼或管理 OAuth 令牌。 Azure Functions 與 Azure Connector 命名空間整合,提供觸發器和 SDK,讓你專注於商業邏輯,而連接器命名空間則負責 webhook、認證和重試。

Note

Azure Functions 的 Azure Connector Namespace 整合功能目前處於公開預覽階段。 功能、設定名稱及特定管理連接器的支援在正式開放(GA)前可能會有所變動。 此功能使用受 Microsoft Azure 預覽補充條款 約束。

目前僅支援 C#、Node.js和 Python 語言堆疊。

連接器如何增強功能

連接器命名空間為函式程式設計模型新增了兩項功能:

  • 連接器觸發程序
    當外部服務發生事件時,函式會執行,例如在 Microsoft 365 中收到新郵件、新增到 SharePoint 的檔案,或是發佈到 Teams 的訊息。 執行階段會公開一個 connectorTrigger 繫結,用來接收來自連接器命名空間的 Webhook 回呼。
  • Connector SDK 動作
    你的函式程式碼是透過 SDK 客戶端呼叫連接器操作。 SDK 涵蓋管理型連接器,如 Microsoft 365 Outlook、Microsoft 365 Users、Teams、SharePoint 及 OneDrive。 尚未具備 SDK 模型的受管理連接器可作為 HTTP 端點呼叫。

你可以搭配傳統函式觸發器和綁定(如 HTTP、計時器、佇列、服務匯流排、Event Grid 和 Durable Functions)來使用受管理連接器。

預覽可用性

Dimension Availability
連接器命名空間區域 任何支援 Connector 命名空間 的區域。
語言 .NET 10 隔離式、Python 3.13+、Node.js 22+(JS/TS)。 Java、PowerShell 和 Go 都不被支援。
主辦計畫 Flex Consumption(建議)、Premium、Dedicated,以及 Container Apps。
定價 Standard Functions 定價:預覽期間,連接器觸發程序/SDK 不另收費。
連接器命名空間有獨立的計費方式。

何時使用連接器

當你的函式主要需要與外部服務互動,而非執行複雜的自訂邏輯時,請使用連接器。 請考慮以下在功能應用程式中使用受管理連接器的方法:

  • 對外部事件的反應
    你的應用程式必須處理外部連接服務引發的事件(新郵件、行事曆邀請、檔案、清單項目、Teams 活動),但你不想花心力編碼 webhook 註冊、握手驗證和 OAuth 刷新。 假設有這樣一種情況:你的函式會執行,以處理傳送到受監控的 Office 365 Outlook 資料夾中的新電子郵件、將郵件分類、呼叫 Office 365 連接器進行擴充,並標記或移動該電子郵件。 所有這些分散式工作都由您的應用程式完成,完全不用擔心重新整理權杖,重新整理權杖是由您的連接器命名空間處理。

  • 替換客製化服務客戶
    你的函式程式碼已經透過自訂的 HTTP 客戶端呼叫 Microsoft 365 或第三方 API,這需要你管理秘密、範圍範圍,並在多個連線間重試政策,這很快就會成為維護負擔。 你可以直接在函式程式碼中使用連接器 SDK 中的型別客戶端,讓受管理連接器自行處理連線。

  • 善用現有的應用程式部署
    你已經建立了一個事件驅動的功能應用專案,包含部署管線和監控工具。 你可以使用受管理連接器在同一專案中新增基於外部服務觸發的功能,並善用現有基礎設施。 例如,過去依賴訊息佇列或邏輯應用的功能式應用程式,現在能直接回應 Teams 活動,並連接 Office 365 進行組織內檢查與經理查詢。

  • 代理工作流程
    您正在建置工作流程,其中函式會接收事件、使用 AI 模型進行推理,然後再透過連接器作業對外部服務執行動作。 你可以利用 Azure Functions 託管技能,為您的代理式工作流程進行程式設計,同時仍可善用以受控連接器為基礎的觸發程序和受控連接器 SDK。

  • 以程式碼為先的控制與管理整合
    你想要管理型連接器來簡化與外部服務的入站與出站通訊,但你偏好以程式碼為先的程式設計模式,並完全掌控編排,包括分支、管理步驟間的認證,以及重複使用現有函式庫。

    Tip

    當工作負載純粹是跨連接器的編排,沒有自訂程式碼時,Logic Apps Standard 仍然是最簡單的選擇。 欲了解更多資訊,請參閱與其他 Azure 整合選項的關係。

與其他 Azure 整合選項的關係

Azure Functions 中的受控連接器可額外新增。 正確的選擇取決於工作負載需要多少自訂程式碼,以及團隊偏好視覺設計師還是程式碼。

Option 適用對象 你會得到...
Logic Apps 標準 跨連接器協調工作流程;團隊偏好視覺設計師;步驟之間有少量自訂程式碼。 適用於相同連接器生態系統的低程式碼設計器。
Azure Functions 搭配受控連接器 以程式碼為優先的體驗,包括自訂分支、進行中函式庫、其他綁定,以及觸發與動作之間的 AI 模型呼叫。 .NET、Python或 Node.js 創作;功能部署與監控;外部服務沒有 webhook 或 OAuth 程式碼。
搭配受控連接器的 Azure App 服務 為現有的網頁應用程式或 API 新增連接器事件與動作。 透過應用程式路由進行認證的 HTTP 回調,以及相同的 Connector SDK 用戶端用於外站操作;接收應用程式的認證則與觸發器分開設定。
具有服務 SDK 的 HTTP 觸發程序 例如目標服務沒有管理連接器,或需要連接器未提供的協定層級控制。 完全控制認證、重試及 webhook 驗證;連接器命名空間沒有要求。

函式應用程式可以使用連接器觸發器和直接服務 SDK,並參與 Logic Apps 的工作流程。 你可以在現有的 HTTP 觸發應用程式中新增連接器觸發器,並逐步採用 SDK 用戶端。

套件與先修條件

每種支援的語言都有一小組套件,負責引入觸發程序綁定和連接器 SDK 用戶端。

背景工作擴充功能套件隨附連接器觸發程序綁定。 Azure.Connectors.Sdk.* 套件 (每個連接器各一個) 隨附具類型的酬載與 SDK 用戶端。

dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Connector --prerelease
dotnet add package Azure.Connectors.Sdk --prerelease

對於 .NET 隔離式背景工作程序,請以 net8.0 或 net10.0 以及最新版本的 Functions 背景工作程序為目標。

Python 會使用預覽版擴充功能套件來載入觸發程序繫結,並使用 azurefunctions-extensions-connectors 套件來載入具型別 Office 365 模型。 將套件組合新增至 host.json:

{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview",
        "version": "[4.42.0, 5.0.0)"
    }
}

安裝執行時與擴充套件:

pip install "azure-functions>=2.2.0b4"
pip install azurefunctions-extensions-connectors

@app.connector_trigger 裝飾項目適用於所有受控連接器類型。 具型別承載模型正透過 azurefunctions-extensions-connectors 套件積極開發並新增。 對於沒有型別模型的管理連接器,將有效載荷視為字串。

Node.js 使用實驗擴充套件來載入觸發綁定。 將套件組合新增至 host.json:

{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview",
        "version": "[4.42.0, 5.0.0)"
    }
}

安裝 Functions 程式庫和連接器套件:

npm install @azure/functions
npm install @azure/functions-extensions-connectors
npm install @azure/connectors

當具類型的模型存在時,請使用 @azure/functions-extensions-connectors 中具類型的進入點 (例如 connectors.office365.onNewEmail)。 當您想要原始酬載資料時,請針對任何受控連接器使用來自 @azure/functions 的 app.connectorTrigger。

Important

Go、Java 和 PowerShell 在公開預覽版中不被支援。 請參閱 預覽可用性 以了解目前支援的執行環境清單。

連接器型觸發程序

當所連線的服務中發生事件時,以受控連接器為基礎的觸發程序會執行你的函式。 連接器命名空間會藉由使用連接器擴充功能的 Webhook 端點,透過 HTTPS 將事件傳遞至您的函式應用程式:

POST /runtime/webhooks/connector?functionName={FunctionName}&code={connector_extension_key}

{FunctionName} 與你 [Function] 屬性中的名字相符。 {connector_extension_key} 是你透過執行來取得的系統金鑰值:

{FunctionName} 與您在 @app.function_name 裝飾項目中的名稱相符。 {connector_extension_key} 是你透過執行來取得的系統金鑰值:

{FunctionName} 與您觸發程序註冊中的名稱相符。 {connector_extension_key} 是你透過執行來取得的系統金鑰值:

az functionapp keys list \
    --resource-group <resource-group> \
    --name <function-app> \
    --query "systemKeys.connector_extension" \
    --output tsv

你連接器命名空間中的觸發設定會儲存該回調 URL,並在每次回調時呈現系統金鑰。 函數執行時會在執行函式前驗證金鑰。 對於沒有共享秘密的設定,你可以在函式應用程式前放置 App Service 內建的認證,並從連接器命名空間驗證管理身份憑證。 完整模式請參見 .NET 範例:內建認證與管理身份。

Tip

預覽期間,請針對連接器觸發的函式使用彈性使用量方案。 彈性使用量提供符合連接器平台驗證模型的個別執行個體擴展和受控識別支援。

請求有效載荷攜帶事件主體及一組 x-ms-* 標頭,用以識別觸發設定、連線、事件類型及相關 ID。 當受管理連接器有 SDK 模型時,執行時會將有效載荷直接反序列化到該模型中。 對於沒有客戶端 SDK 的託管連接器,函式會接收原始的 JSON 主體。

以下範例顯示當 Office 365 Outlook 信箱收到新電子郵件時會觸發的函式。 觸發標記是按語言進行的;連接器命名空間中的觸發配置在所有情況下都是相同的。

using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Connector;
using Azure.Connectors.Sdk.Office365.Models;
using Microsoft.Extensions.Logging;

public class OnNewEmail
{
    private readonly ILogger<OnNewEmail> _logger;

    public OnNewEmail(ILogger<OnNewEmail> logger) => _logger = logger;

    [Function("OnNewEmail")]
    public IActionResult Run(
        [ConnectorTrigger()] Office365OnNewEmailTriggerPayload payload)
    {
        var emails = payload?.Body?.Value ?? [];
        foreach (var email in emails)
        {
            _logger.LogInformation(
                "Received email from {From} with subject '{Subject}'.",
                email.From, email.Subject);
        }

        return new OkResult();
    }
}

Office365OnNewEmailTriggerPayload 模型及其他操作有效載荷類型來自 Azure.Connectors.Sdk.Office365.Models。 如需查看作業到承載資料的完整對應,請參閱 作業到 Azure Functions 函式簽章對應。

import azure.functions as func
import json
import logging

app = func.FunctionApp()

@app.function_name(name="OnNewEmail")
@app.connector_trigger(arg_name="payload")
def on_new_email(payload: str) -> None:
    data = json.loads(payload)
    emails = data.get("body", {}).get("value", [])
    for email in emails:
        logging.info(
            "Received email from %s with subject '%s'.",
            email.get("from"), email.get("subject"))

具體而言,針對 Office 365 OnNewEmailV3 作業,您可以使用 azurefunctions-extensions-connectors 中的具型別裝飾項目:

import azure.functions as func
import azurefunctions.extensions.connectors.office365 as office365
import logging

app = func.FunctionApp()

@app.function_name(name="OnNewEmail")
@app.connector_trigger(arg_name="email")
def on_new_email(email: office365.ClientReceiveMessage) -> None:
    logging.info(
        "Received email from %s with subject '%s'.",
        email.from_, email.subject)
import { InvocationContext } from '@azure/functions';
import {
    connectors,
    EmailTriggerContext,
} from '@azure/functions-extensions-connectors';

connectors.office365.onNewEmail('OnNewEmail', {
    handler: async (
        context: EmailTriggerContext,
        invocationContext: InvocationContext,
    ) => {
        for (const email of context.emails) {
            invocationContext.log(
                `Received email from '${email.from}' with subject '${email.subject}'.`,
            );
        }
    },
});

針對尚未具備具型別進入點的任何連接器,請使用 app.connectorTrigger 中的一般 @azure/functions:

import { app, InvocationContext } from '@azure/functions';

app.connectorTrigger('OnNewItem', {
    handler: async (payload: unknown, context: InvocationContext) => {
        const data = typeof payload === 'string' ? JSON.parse(payload) : payload;
        const items: Record<string, unknown>[] = (data as any)?.body?.value ?? [];
        for (const item of items) {
            context.log(`Item ID: ${item.Id}`);
        }
    },
});

Important

公開預覽期間,此語言無法使用連接器觸發程序。

你可以在連接器命名空間中使用 Azure CLI、ARM 或 Bicep 來建立觸發設定。 這個步驟是連接器平台的一部分,並記錄在連接器內容集中。 Functions 沒有提供自己的觸發器註冊設定指令。

驗證您的函式以存取連接器命名空間

Note

本節介紹連接器命名空間與 your function app 之間的認證。 關於連接器命名空間如何與上游服務(Microsoft 365、Teams、SharePoint)進行認證,請參閱 Azure 連接器總覽。

預設的認證模型使用連接器命名空間在每次回調時呈現的共享系統金鑰(connector_extension)。 然而,共享金鑰無法在每個觸發器之間設定作用範圍,且需要在函式應用程式與連接器命名空間間協調輪換。 對於生產工作負載,則改用 App Service 內建的認證 (也稱為 Easy Auth)搭配管理身份。

在此模式中,連接器命名空間使用其系統指派或使用者指派的受控身分識別,為每個回撥請求 Entra ID 權杖。 函式應用程式會在任何要求到達 Functions 主機之前,驗證該權杖,包括其對象、簽發者和呼叫端的物件 ID。 沒有共用金鑰,沒有客戶端秘密,任何地方都沒有。

如需端對端的可運作範例,請參閱此儲存庫:functions-connectors-net-builtinauth。

函數應用程式設定

內建驗證會在 App Service 工作處理序層進行,也就是在 Functions 執行階段收到要求之前。 你可以透過 authsettingsV2 ARM 屬性或 Bicep 中的等效物件來設定。

Setting Purpose
requireAuthentication: true 拒絕任何無有效令牌的請求(回傳 401)。
identityProviders.azureActiveDirectory.enabled: true 驗證Entra ID代幣。
registration.clientId 內建驗證會用來驗證權杖的 Entra 應用程式註冊之應用程式 (用戶端) ID。
registration.openIdIssuer 您租用戶的簽發者 URL:https://login.microsoftonline.com/{tenantId}/v2.0。
validation.allowedAudiences Entra 應用程式的用戶端 ID 與識別碼 URI。 權杖必須在 aud 宣告中帶有這些對象之一。
validation.defaultAuthorizationPolicy.allowedPrincipals.identities 受管理身份的物件(主體)ID 允許呼叫該函式。 此處僅應列出連接器命名空間的管理身份。 任何具有不同 oid 宣告的權杖都會取得 403。

函式應用程式也需要使用者指派受控識別,並與 Entra 應用程式註冊建立聯合。 內建認證利用該 聯邦身份憑證 (FIC)來鑄造 Entra 應用程式的客戶端聲明,且不儲存用戶端機密。 Bicep 模式會將 clientSecretSettingName 設定為保存使用者指派 MI 用戶端 ID 的應用程式設定,告知內建驗證使用 FIC 而不是祕密。

由於內建驗證已經驗證了每個要求,因此你可以在 host.json 中停用多餘的系統金鑰檢查,如下列 JSON 片段所示:

{
    ...
    "extensions": {
        "connector": {
            "system": {
                "webhookAuthorizationLevel": "Anonymous"
            }
        }
    }
}

連接器命名空間配置

你的連接器命名空間必須啟用並附加系統指派或使用者指派的管理身份。 建立觸發器設定時,請為使用者指派的身份指定 authentication.type = ManagedServiceIdentity 和 authentication.identity = <resource-id-of-managed-identity> ,或省略 identity 系統指派的身份。 同時也要指定 authentication.audience = <entra-app-client-id>,讓連接器執行階段知道要在權杖中請求哪個對象。

連接器執行時會利用該受管理身份在每次回調時產生 Entra ID 標記。 在這個權杖中,iss (發行者) 是您的租用戶,aud (對象) 是 Entra 應用程式用戶端識別碼,oid (物件識別碼) 是身分識別的主體識別碼。 內建的認證能驗證這三者。

連接器命名空間資源也需要存取該連線,例如 office365 連線。 透過列出受控身分識別主體識別碼的存取原則,授與此存取權。 範例 bicep 檔案展示了命名空間身份與連線存取政策的完整設定。

執行事項

內建驗證會依序驗證權杖:

  1. 令牌存在 - 401 →缺少或過期的令牌
  2. 簽章 - 針對您租用戶的簽發者 JWKS 進行驗證
  3. iss (發行人) - 必須符合 openIdIssuer
  4. aud (觀眾) - 必須位於 allowedAudiences 中
  5. oid (物件/主體 ID) - 必須與 中的 allowedPrincipals.identities某一個身份相符。 任何其他身分識別 → 403

因為這個檢查是在 App Service 邊緣執行,你的函式程式碼永遠不會看到非來自連接器命名空間管理身份的請求。 你不需要申請碼來進行門禁檢查。

身份驗證流程

┌─────────────────────────────────────────────────────────────────┐
│  Connector namespace                                            │
│  • System-assigned or user-assigned managed identity enabled    │
│  • Trigger config: authentication.type = ManagedServiceIdentity │
│                    authentication.audience = <Entra app ID>     │
│                    callbackUrl = https://<func>/runtime/…       │
└────────────────────────┬───────────────────────────────────────┘
                         │
                         │  POST callbackUrl
                         │  Authorization: Bearer <AAD token>
                         │     iss = your tenant
                         │     aud = Entra app clientId
                         │     oid = managed identity principalId
                         ▼
┌──────────────────────────────────────────────────────────────┐
│  Function App                                                │
│                                                              │
│   ┌──────────────────────────────────────────────────────┐   │
│   │ Built-in authentication  (App Service edge)          │   │
│   │   • Validates signature, iss, aud, exp               │   │
│   │   • Checks oid ∈ allowedPrincipals.identities        │   │
│   │   → No token  → 401                                  │   │
│   │   → Wrong oid → 403                                  │   │
│   └────────────────────┬─────────────────────────────────┘   │
│                        │ pass                                │
│                        ▼                                     │
│   ┌──────────────────────────────────────────────────────┐   │
│   │ /runtime/webhooks/connector                          │   │
│   │   (webhookAuthorizationLevel = Anonymous)            │   │
│   └────────────────────┬─────────────────────────────────┘   │
│                        ▼                                     │
│   ┌──────────────────────────────────────────────────────┐   │
│   │ Your function(payload)                               │   │
│   └──────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────┘
                         ▲
                         │ FIC (federated identity credential)
         ┌───────────────┴────────────────┐
         │  Entra app registration         │
         │  (federated to function-app MI) │
         └─────────────────────────────────┘

在程式碼中使用連接器

連接器 SDK 可讓您的函式將連接器作業作為輸出動作來呼叫。 用戶端介面在連接器命名空間中,使用與觸發程序所用相同的底層受控連接器,因此單一受控連接器即可同時支援同一服務帳戶的輸入觸發程序和輸出呼叫。

在 .NET 中,每個連接器會附送一個型別客戶端(例如 Office365Client、Office365UsersClient、TeamsClient),格式為 Azure.Connectors.Sdk.{Service}。 用戶端建構子會取得連線的執行時 URL 和一個憑證。

以下模式取自 端對端電子郵件使用者查詢 Teams 範例:

using Azure.Core;
using Azure.Identity;
using Azure.Connectors.Sdk.Office365;
using Azure.Connectors.Sdk.Office365Users;
using Azure.Connectors.Sdk.Teams;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
    ManagedIdentityClientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")
});

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddSingleton<TokenCredential>(credential);

        services.AddSingleton(sp => new Office365Client(
            new Uri(Environment.GetEnvironmentVariable("OFFICE365_CONNECTION_RUNTIME_URL")!),
            sp.GetRequiredService<TokenCredential>()));

        services.AddSingleton(sp => new Office365UsersClient(
            new Uri(Environment.GetEnvironmentVariable("OFFICE365USERS_CONNECTION_RUNTIME_URL")!),
            sp.GetRequiredService<TokenCredential>()));

        services.AddSingleton(sp => new TeamsClient(
            new Uri(Environment.GetEnvironmentVariable("TEAMS_CONNECTION_RUNTIME_URL")!),
            sp.GetRequiredService<TokenCredential>()));
    })
    .Build();

host.Run();

*_CONNECTION_RUNTIME_URL 設定指向位於連接器命名空間中的各連線執行階段端點。 將用戶端插入函式,並呼叫具型別方法,例如 UserProfileAsync、GetEmailsAsync 或 FlagAsync。 你也可以從非連接器觸發器呼叫 SDK 客戶端(例如,發佈到 Teams 的 HTTP 觸發器)。

在 Python 中,為有型別的用戶端安裝 azure-connectors(例如 office365、teams、office365Users)。 用戶端接受每個連線的執行時 URL 與憑證。 SDK 可支援的操作範圍正在擴大。

在 Node.js中,為類型客戶端安裝@azure/connectors(例如 office365, , teamsoffice365Users)。 用戶端接受每個連線的執行時 URL 與憑證。 SDK 可支援的操作範圍正在擴大。

Important

連接器 SDK 在公開預覽版中無法提供這些語言版本。