使用 mssql-python 的 Microsoft Entra 驗證

Microsoft Entra ID 透過 mssql-python 驅動程式,為 Azure SQL Database、Azure SQL 受控執行個體 及 Microsoft Fabric 中的 SQL 資料庫提供基於身份的認證。 Microsoft Entra 認證相較於 SQL 認證提供以下功能:

  • 透過 Microsoft Entra ID 進行集中式身份管理。
  • 基於憑證的認證,消除了密碼的需求。
  • 支援條件存取政策。
  • Azure 裝載應用程式的受控識別。

mssql-python 驅動程式支援七種 Microsoft Entra 認證模式,皆透過 Authentication 連接字串 關鍵字設定。

認證模式

將 連接字串 中的關鍵字設Authentication為以下其中一個值:

認證值 描述
ActiveDirectoryDefault 使用 DefaultAzureCredential,會自動嘗試多種方法。
ActiveDirectoryInteractive 基於瀏覽器的互動式登入。
ActiveDirectoryDeviceCode 請在 https://microsoft.com/devicelogin 輸入代碼。
ActiveDirectoryPassword Microsoft Entra ID 的使用者名稱和密碼 已棄用。
ActiveDirectoryMSI 受控識別(系統指派或使用者指派)。
ActiveDirectoryServicePrincipal 具有用戶端識別碼和密碼的服務主體。
ActiveDirectoryIntegrated 與 Microsoft Entra ID 整合的 Windows(Kerberos)

Note

ActiveDirectoryDefaultActiveDirectoryInteractiveActiveDirectoryDeviceCode 模式需要 azure-identity 套件。 使用 pip install azure-identity 安裝。

DefaultAzureCredential (預設Azure憑證)

ActiveDirectoryDefault 模式使用 Azure Identity SDK 中的 DefaultAzureCredential,並依序嘗試下列驗證方法:

  1. 環境變數。
  2. Kubernetes 的工作負載身分。
  3. 管理式身分
  4. Azure CLI 認證
  5. Azure PowerShell 認證
  6. Azure Developer CLI 認證。
  7. 互動式瀏覽器(如果啟用)。

範例:預設認證

以下範例與 ActiveDirectoryDefault連接,該鏈利用 DefaultAzureCredential 鏈條自動尋找有效憑證:

import mssql_python

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDefault;"
    "Encrypt=yes;"
)

cursor = conn.cursor()
cursor.execute("SELECT USER_NAME()")
print(f"Connected as: {cursor.fetchval()}")

本地開發時使用此模式,因為它會自動擷取 Azure CLI 憑證。 在生產環境中,請使用特定的認證模式(ActiveDirectoryMSIActiveDirectoryServicePrincipal)。 DefaultAzureCredential 每次第一次連線都會經過多個憑證提供者,這會增加生產工作負載不需要的延遲。

互動式驗證

對於互動式應用程式,請使用瀏覽器認證。 使用者必須擁有使用 CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER 建立的資料庫帳戶。 完整前提條件請參閱配置 Microsoft Entra 認證

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryInteractive;"
    "Encrypt=yes;"
)

在 Windows 上,此模式會委派給 ODBC 驅動程式的原生互動流程。 在其他平台上,它使用 Azure Identity SDK 的瀏覽器認證。

裝置程式碼驗證

對於沒有瀏覽器的環境,例如SSH會話或容器,請使用裝置碼驗證。 使用者必須擁有使用 CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER 建立的資料庫帳號。 關於前置條件,請參見配置 Microsoft Entra 認證

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDeviceCode;"
    "Encrypt=yes;"
)
# Output: To sign in, use a web browser to open https://microsoft.com/devicelogin
# and enter the code XXXXXXX to authenticate.

依照指示在另一台裝置的瀏覽器中進行驗證。

服務主體帳戶驗證

對於不需要使用者互動的自動化應用程式,請使用服務主體認證:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryServicePrincipal;"
    "UID=<client-id>;"       # Application (client) ID
    "PWD=<client-secret>;"   # Client secret
    "Encrypt=yes;"
)

建立服務主體

  1. 在 Microsoft Entra ID 註冊應用程式
  2. 建立用戶端秘密。
  3. 授權服務負責人存取您的資料庫:
-- In Azure SQL
CREATE USER [app-name] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [app-name];
ALTER ROLE db_datawriter ADD MEMBER [app-name];

Tip

如果 CREATE USER 因錯誤 33131 而失敗(顯示名稱重複),請使用 WITH OBJECT_ID,從 Azure 入口網站中的 企業應用程式 頁面(而不是應用程式註冊頁面)指定服務主體的物件 ID:

CREATE USER [app-name] FROM EXTERNAL PROVIDER
    WITH OBJECT_ID = '<enterprise-app-object-id>';

如需詳細資訊,請參閱 Microsoft Entra 登入和具有非唯一顯示名稱的使用者

受管理的識別

對於 Azure 託管的應用程式,例如 App Service、Azure Functions 和 VMS,使用管理身份認證:

系統指派的管理身份識別

使用 直接指派給 Azure 資源的身份來連接:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryMSI;"
    "Encrypt=yes;"
)

使用者指派的受控識別

請在欄位 UID 中指定使用者指派的管理身份的用戶端 ID:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryMSI;"
    "UID=<managed-identity-client-id>;"
    "Encrypt=yes;"
)

設定資料庫存取

在你的資料庫中授予管理身份存取權限。 在建立外部使用者之前,伺服器必須先設定 Microsoft Entra 管理員。 若要在您的 Azure 資源上啟用受管理身份,請參閱 Azure 資源的管理身份

-- Replace 'my-app-service' with your Azure resource name
CREATE USER [my-app-service] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [my-app-service];
ALTER ROLE db_datawriter ADD MEMBER [my-app-service];

密碼驗證(已棄用)

Important

ActiveDirectoryPassword 驗證選項(Microsoft Entra ID 密碼驗證)在 Microsoft SQL 驅動程式中已被棄用。 這種高風險的認證流程與強制的 Microsoft Entra 多重驗證(MFA)不相容,且在強制執行多重驗證的租戶中可能無法運作。 計劃遷移到不同的 Microsoft Entra 認證方式。

Microsoft Entra ID 的密碼驗證基於 OAuth 2.0 資源擁有者密碼憑證(ROPC)授權,允許應用程式直接處理使用者的密碼來登入。

Microsoft 建議不要使用 ROPC 流程,因為它與多重認證(MFA)不相容。 在大部分情況下,有更安全的替代方案可供使用,並建議使用。 這種流程需要對應用程式高度信任,且存在其他流程中不存在的風險。 只有在無法用更安全的流程時才使用這個流程。 Microsoft 正逐步放棄這種高風險的認證流程,以保護使用者免受惡意攻擊。 欲了解更多資訊,請參閱 Azure 強制多重驗證的規劃

當使用者在登入時,請使用 ActiveDirectoryInteractive 或 ActiveDirectoryIntegrated 認證,使登入使用者的稽核憑證及條件存取政策得以適用。

對於服務對服務的無人值守情境,請遵循 Microsoft Entra 服務帳戶指導方針

  • 如果你的應用程式是在 Azure 基礎設施上執行,請使用 ActiveDirectoryMSI(或某些驅動程式中的 ActiveDirectoryManagedIdentity)。 受管理身份消除了維護與輪替秘密與憑證的負擔。
  • 如果無法使用受管理身份(例如應用程式在 Azure 外執行),則使用 ActiveDirectoryServicePrincipal。 在驅動程式支援時,偏好使用用戶端憑證而非用戶端秘密。 使用憑證時,私鑰會留在用戶端,只有簽署的斷言會送給 Microsoft Entra 以驗證客戶端。 如果金鑰儲存在硬體(如 TPM 或 HSM)或標記為不可匯出,就無法像用戶端秘密那樣以字串形式複製。
  • 不要把 Microsoft Entra 使用者帳號當作服務帳號使用。

當你需要用 Microsoft Entra 帳號設定使用者名稱和密碼時,請使用密碼驗證。 使用者必須先建立一個以 CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER 建立的資料庫帳戶:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryPassword;"
    "UID=<login@domain.com>;"
    "PWD=<password>;"
    "Encrypt=yes;"
)

Windows 整合認證

對於使用 Kerberos 的已加入網域 Windows 環境,請使用 Windows 整合認證。 此模式要求您的內部部署 Active Directory 與 Microsoft Entra ID 建立同盟,並且已在伺服器上設定 Microsoft Entra 系統管理員

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryIntegrated;"
    "Encrypt=yes;"
)

此模式使用目前 Windows 使用者的 Kerberos 憑證。 在 Linux 和 macOS 上,您必須手動配置 Kerberos(krb5.conf 以及有效的 keytab 或票證)。 請參閱 在 Linux 上搭配 SQL Server 使用 Active Directory 驗證,以了解用戶端 Kerberos 的設定。

存取令牌驗證

你可以透過外部取得代幣,例如透過自訂代幣提供者或共享代幣快取。 在這些情況下,使用 SQL_COPT_SS_ACCESS_TOKEN 搭配 attrs_before 參數來直接傳遞權杖。 此方法繞過驅動程式內建的代幣獲取流程。

import mssql_python
from azure.identity import DefaultAzureCredential
import struct

def get_token():
    credential = DefaultAzureCredential(
        exclude_interactive_browser_credential=False
    )
    token_bytes = credential.get_token(
        "https://database.windows.net/.default"
    ).token.encode("utf-16le")
    token_struct = struct.pack(
        f'<I{len(token_bytes)}s', len(token_bytes), token_bytes
    )
    return token_struct

SQL_COPT_SS_ACCESS_TOKEN = 1256

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;",
    attrs_before={SQL_COPT_SS_ACCESS_TOKEN: get_token()}
)

Important

使用 SQL_COPT_SS_ACCESS_TOKEN時,連接字串 不得包含 UIDPWDAuthenticationTrusted_Connection。 憑證本身負責認證。

選擇驗證模式

Scenario 推薦模式
開發機器 ActiveDirectoryDefault(使用 Azure CLI)
Azure App 服務 / Functions ActiveDirectoryMSI (比預設還快)
Azure Kubernetes Service ActiveDirectoryDefault (工作負載識別)
內部部署的自動化指令碼 ActiveDirectoryServicePrincipal
互動式桌面應用程式 ActiveDirectoryInteractive
沒有瀏覽器的 SSH/容器 ActiveDirectoryDeviceCode

Troubleshoot

「使用者『NT AUTHORITY\ANONYMOUS LOGON』登入失敗」

確認使用者或受管理身份是否存在於資料庫中:

CREATE USER [identity-name] FROM EXTERNAL PROVIDER;

「AADSTS700016:找不到申請」

服務負責人或應用程式ID錯誤。 確認客戶端 ID 以及該應用程式是否已註冊在您的 Microsoft Entra 租戶中。

「管理身份端點無法到達」

  • 確認 Azure 資源是否啟用了受管理身份。
  • 對於使用者指定的身份,請確認客戶端 ID 是否正確。
  • 檢查該資源是否能存取身份端點的網路。

代幣取得逾時

ActiveDirectoryDefault 使用 DefaultAzureCredential,依序檢查憑證提供者鏈,直到其中一個成功為止。 這種依序巡覽提供者鏈的方式,會在第一次連線時增加幾秒的延遲,尤其是當鏈中較前面的提供者(環境變數、工作負載身分識別)在找到實際可用的提供者之前就失敗時。 在生產環境中,直接指定憑證類型以跳過該鏈:

# Slow: DefaultAzureCredential tries multiple providers
conn = mssql_python.connect(connection_string, authentication="ActiveDirectoryDefault")

# Fast: Skip directly to managed identity
conn = mssql_python.connect(connection_string, authentication="ActiveDirectoryMSI")