本文介绍如何通过mssql-django后端将 SQL Server Always Encrypted 与 Django 应用程序配合使用。 Always Encrypted 提供列级加密,用于保护静态和传输中的敏感数据。
先决条件
- 适用于 SQL Server 的 Microsoft ODBC Driver 17 或 18
- SQL Server 2016 或更高版本,或Azure SQL 数据库
- 在SQL Server端配置的列加密(列主密钥和列加密密钥)
工作原理
Always Encrypted 由 ODBC 驱动程序层处理,而不是由 Django 本身处理。 启用 ColumnEncryption ODBC 参数时,驱动程序会在应用程序与SQL Server之间传递时自动加密和解密数据。 无论列是否被加密,Django 模型和查询的工作方式都是相同的。
Windows 证书存储
当列主密钥存储在 Windows 证书存储中时,通过将 ColumnEncryption=Enabled 添加到 extra_params 中来启用 Always Encrypted:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"USER": "<your-username>",
"PASSWORD": "<your-password>",
"HOST": "<your-server>",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": "ColumnEncryption=Enabled",
},
},
}
此方法仅适用于Windows。
使用客户端 ID 和机密的 Azure 密钥保管库
当列主密钥存储在 Azure 密钥保管库 中时,请在 extra_params 中提供应用程序凭据:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"USER": "<your-username>",
"PASSWORD": "<your-password>",
"HOST": "<your-server>",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": (
"ColumnEncryption=Enabled;"
"KeyStoreAuthentication=KeyVaultClientSecret;"
"KeyStorePrincipalId=<application-client-id>;"
"KeyStoreSecret=<client-secret>"
),
},
},
}
将 <application-client-id> 和 <client-secret> 替换为应用注册的 应用程序(客户端)ID 和客户端密码值。
Important
不要在 settings.py 中硬编码密钥。 使用环境变量或机密管理器在运行时提供凭据。
带有托管标识的 Azure 密钥保管库
在Azure(例如,Azure 虚拟机或Azure 应用服务)上运行时,请使用托管标识访问Azure 密钥保管库。
系统分配的托管标识
除 KeyStoreAuthentication 参数外,无需额外配置:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"HOST": "<your-server>.database.windows.net",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": (
"ColumnEncryption=Enabled;"
"KeyStoreAuthentication=KeyVaultManagedIdentity"
),
},
},
}
用户分配的管理标识
包括托管标识的客户端 ID(也称为应用程序 ID):
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"HOST": "<your-server>.database.windows.net",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": (
"ColumnEncryption=Enabled;"
"KeyStoreAuthentication=KeyVaultManagedIdentity;"
"KeyStorePrincipalId=<managed-identity-client-id>"
),
},
},
}
授予托管标识权限
授予托管标识对 Azure SQL 数据库的访问权限:
CREATE USER [<identity-name>] FOR EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER [<identity-name>]; ALTER ROLE db_datawriter ADD MEMBER [<identity-name>]; GRANT VIEW ANY COLUMN MASTER KEY DEFINITION TO [<identity-name>]; GRANT VIEW ANY COLUMN ENCRYPTION KEY DEFINITION TO [<identity-name>];使用 Always Encrypted Azure 密钥保管库 文档中列出的权限,向托管标识授予对存储列主密钥的 Azure 密钥保管库的访问权限。
让 Django 管理加密表
将 Always Encrypted 与 Django 配合使用时,请先在 SQL Server 上配置加密对象,然后运行迁移。
推荐顺序:
- 在SQL Server或Azure SQL上创建列主密钥(CMK)和列加密密钥(CEK)。
- 在 Django 连接设置中配置
ColumnEncryption=Enabled。 - 执行 Django 迁移。
- 使用 SQL Server Management Studio 或 T-SQL 加密目标列。
执行迁移:
python manage.py migrate
mssql-django 不会创建或管理 Always Encrypted 密钥元数据。 密钥创建和列加密策略仍SQL Server管理任务。
不支持的身份验证方法
Always Encrypted 密钥存储访问不支持用户名/密码和Azure 密钥保管库交互式身份验证。