Docs 菜单
Docs 主页
/ /

教程:使用 Django MongoDB后端Queryable Encryption

在本教程中,您可以学习;了解如何在 Django应用程序中使用Queryable Encryption (QE)。

MongoDB 的Queryable Encryption功能通过自动加密敏感数据来帮助保护敏感数据,同时仍然允许应用程序与加密数据进行交互。在本教程中,您可以通过在应用程序设置中启用加密并选择要加密的模型字段学习;了解如何将Queryable Encryption与 Django MongoDB后端结合使用。

在开始本教程之前,请完成以下先决任务:

  • 创建MongoDB Atlas帐户并配置集群。确保您的集群在MongoDB Server7.0 或更高版本上运行。要学习;了解更多信息,请参阅 MongoDB入门指南。

  • 下载自动加密共享库。要查看说明,请参阅《安装和配置查询分析组件》指南。这些说明展示了如何导航到MongoDB下载中心并填写下载库所需的表格。

  • 安装Python3.10 或更高版本。

在本教程中,您将创建一个使用 Django MongoDB后端的Queryable Encryption应用程序。该应用程序安全地处理医疗记录:它对敏感医疗信息进行加密、解密和查询。

提示

完整的应用程序

要查看本教程的完整示例应用程序,请参阅 GitHub 上的 django_qe 文件夹。

按照本节中的步骤安装项目依赖项、配置环境并创建应用程序结构。

1

选择与操作系统对应的标签页,运行以下命令激活虚拟环境,安装 Django MongoDB后端,并安装Queryable Encryption依赖项:

python -m venv venv
source venv/bin/activate
pip install 'django-mongodb-backend[encryption]'
python -m venv venv
. venv\Scripts\activate
pip install 'django-mongodb-backend[encryption]'

pip install 'django-mongodb-backend[encryption]' 命令会安装 Django MongoDB后端、最新的PyMongo版本以及所需的Python依赖项。

注意

适用于 v6.0.1

Queryable Encryption需要 Django MongoDB后端 v6.0.1 或更高版本。前面的命令会安装所需的版本。

2

从Shell中运行以下命令,根据自定义模板创建一个名为 django_qe 的新 Django项目:

django-admin startproject django_qe --template https://github.com/mongodb-labs/django-mongodb-project/archive/refs/heads/6.0.x.zip

此命令创建一个 django_qe项目目录并添加初始文件框架。

3

From your django_qe directory, run the following command to create an application called medical_records:

python manage.py startapp medical_records

此命令在项目中创建一个 medical_records应用程序目录并添加默认应用文件,包括模型和设置的文件。

4

导航到 django_qe目录中的 settings.py文件,并编辑 INSTALLED_APPS 设置以类似于以下代码:

INSTALLED_APPS = [
'medical_records.apps.MedicalRecordsConfig',
'django_qe.apps.MongoAdminConfig',
'django_qe.apps.MongoAuthConfig',
'django_qe.apps.MongoContentTypesConfig',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_mongodb_backend',
]

此设置可确保在您的项目中启用 medical_records应用。

设置项目后,请按照本节中的步骤连接到MongoDB并创建存储加密数据的模型。

1

django_qe目录中,导航到 settings.py文件。将 DATABASES 设置替换为以下代码:

DATABASES = {
'default': {
'ENGINE': 'django_mongodb_backend',
'HOST': '<connection string>',
'NAME': 'db',
},
}

<connection string> 占位符替换为连接到集群的连接字符串。

此代码将 Django应用程序配置为连接到MongoDB并默认访问权限名为 db 的数据库。此配置适用于非加密模型。

2

settings.py文件中,您可以在 DATABASES 设置中指定 encrypted 密钥,以启用Queryable Encryption并设立密钥管理系统 (KMS)提供商。 Django MongoDB后端支持 AWS、 Azure、 GCP、KMIP 和本地KMS提供商。

警告

本地集合扫描存储

如果您将客户主密钥(集合扫描 )存储在本地,请勿在生产环境中使用此应用程序。如果没有远程KMS,您可能会面临未经授权访问权限加密密钥或丢失解密数据所需密钥的风险。

提示

密钥管理系统

要学习;了解有关KMS 的更多信息,请参阅“密钥管理”维基百科条目。

选择与您的KMS对应的标签页,然后修改 DATABASES 设置以类似于以下示例:

DATABASES = {
'default': {
# ... Your default configuration
},
'encrypted': {
'ENGINE': 'django_mongodb_backend',
'HOST': '<connection string>',
'NAME': 'medical_records',
# ...
'OPTIONS': {
'auto_encryption_opts': AutoEncryptionOpts(
key_vault_namespace='medical_records.__keyVault',
kms_providers={
'local': {
# Generated by os.urandom(96)
'key': (
b'-\xc3\x0c\xe3\x93\xc3\x8b\xc0\xf8\x12\xc5#b'
b'\x19\xf3\xbc\xccR\xc8\xedI\xda\\ \xfb\x9cB'
b'\x7f\xab5\xe7\xb5\xc9x\xb8\xd4d\xba\xdc\x9c'
b'\x9a\xdb9J]\xe6\xce\x104p\x079q.=\xeb\x9dK*'
b'\x97\xea\xf8\x1e\xc3\xd49K\x18\x81\xc3\x1a"'
b'\xdc\x00U\xc4u"X\xe7xy\xa5\xb2\x0e\xbc\xd6+-'
b'\x80\x03\xef\xc2\xc4\x9bU'
)
},
},
crypt_shared_lib_path='<Automatic Encryption Shared Library path>',
crypt_shared_lib_required=True,
)
},
},
}

将以下占位符值替换为:

  • <connection string>:与您在 default 键中指定的连接字符串相同

  • <Automatic Encryption Shared Library path>:自动加密共享库的完整路径

DATABASES = {
'default': {
# ... Your default configuration
},
'encrypted': {
'ENGINE': 'django_mongodb_backend',
'HOST': '<connection string>',
'NAME': 'medical_records',
# ...
'OPTIONS': {
'auto_encryption_opts': AutoEncryptionOpts(
key_vault_namespace='medical_records.__keyVault',
kms_providers={
'aws': {
'accessKeyId': '<AWS Access Key ID>',
'secretAccessKey': '<AWS Secret Access Key>',
},
},
crypt_shared_lib_path='<Automatic Encryption Shared Library path>',
crypt_shared_lib_required=True,
)
},
'KMS_CREDENTIALS': {
'aws': {
'key': '<AWS Key ARN>',
'region': '<AWS Key Region>',
},
},
},
}

将以下占位符值替换为:

  • <connection string>:与您在 default 键中指定的连接字符串相同

  • <AWS Access Key ID>:您的Amazon Web Services访问密钥ID

  • <AWS Secret Access Key>:您的Amazon Web Services秘密访问权限密钥

  • <Automatic Encryption Shared Library path>:自动加密共享库的完整路径

  • <AWS Key ARN>:AWS 客户的Amazon资源名称。

  • <AWS Key Region>:您的 AWS地区,例如 'us-east-1'

DATABASES = {
'default': {
# ... Your default configuration
},
'encrypted': {
'ENGINE': 'django_mongodb_backend',
'HOST': '<connection string>',
'NAME': 'medical_records',
# ...
'OPTIONS': {
'auto_encryption_opts': AutoEncryptionOpts(
key_vault_namespace='medical_records.__keyVault',
kms_providers={
'azure': {
'tenantId': '<Azure Tenant ID>',
'clientId': '<Azure Client ID>',
'clientSecret': '<Azure Client Secret>',
},
},
crypt_shared_lib_path='<Automatic Encryption Shared Library path>',
crypt_shared_lib_required=True,
)
},
'KMS_CREDENTIALS': {
'azure': {
'keyVaultEndpoint': '<Azure Key Vault Endpoint>',
'keyName': '<Azure Key Name>',
# Optional: 'keyVersion': '<Azure Key Version>',
},
},
},
}

将以下占位符值替换为:

  • <connection string>:与您在 default 键中指定的连接字符串相同

  • <Azure Tenant ID>:您的Azure Active Directory 租户ID

  • <Azure Client ID>:您的Azure应用程序客户端ID

  • <Azure Client Secret>: Your Azure application client secret

  • <Automatic Encryption Shared Library path>:自动加密共享库的完整路径

  • <Azure Key Vault Endpoint>:您的Azure Key Vault端点URL。

  • <Azure Key Name>: The name of your key in Azure Key Vault

  • <Azure Key Version>:(可选)要使用的密钥版本

DATABASES = {
'default': {
# ... Your default configuration
},
'encrypted': {
'ENGINE': 'django_mongodb_backend',
'HOST': '<connection string>',
'NAME': 'medical_records',
# ...
'OPTIONS': {
'auto_encryption_opts': AutoEncryptionOpts(
key_vault_namespace='medical_records.__keyVault',
kms_providers={
'gcp': {
'email': '<GCP Service Account Email>',
'privateKey': '<GCP Service Account Private Key>',
},
},
crypt_shared_lib_path='<Automatic Encryption Shared Library path>',
crypt_shared_lib_required=True,
)
},
'KMS_CREDENTIALS': {
'gcp': {
'projectId': '<GCP Project ID>',
'location': '<GCP Key Ring Location>',
'keyRing': '<GCP Key Ring Name>',
'keyName': '<GCP Key Name>',
},
},
},
}

将以下占位符值替换为:

  • <connection string>:与您在 default 键中指定的连接字符串相同

  • <GCP Service Account Email>:您的 Google Cloud 服务帐号电子邮件

  • <GCP Service Account Private Key>:您的 Google Cloud 服务帐号私钥

  • <Automatic Encryption Shared Library path>:自动加密共享库的完整路径

  • <GCP Project ID>:您的 Google Cloud项目ID

  • <GCP Key Ring Location>:密钥环的位置,例如 'global'

  • <GCP Key Ring Name>:密钥环的名称

  • <GCP Key Name>:密钥的名称

DATABASES = {
'default': {
# ... Your default configuration
},
'encrypted': {
'ENGINE': 'django_mongodb_backend',
'HOST': '<connection string>',
'NAME': 'medical_records',
# ...
'OPTIONS': {
'auto_encryption_opts': AutoEncryptionOpts(
key_vault_namespace='medical_records.__keyVault',
kms_providers={
'kmip': {
'endpoint': '<KMIP Server Endpoint>',
},
},
crypt_shared_lib_path='<Automatic Encryption Shared Library path>',
crypt_shared_lib_required=True,
)
},
'KMS_CREDENTIALS': {
'kmip': {
# Optional: 'keyId': '<KMIP Key Identifier>',
},
},
},
}

将以下占位符值替换为:

  • <connection string>:与您在 default 键中指定的连接字符串相同。

  • <KMIP Server Endpoint>:KMIP服务器端点及其端口,例如 'example.com:443'

  • <Automatic Encryption Shared Library path>:自动加密共享库的完整路径。

  • <KMIP Key Identifier>:(可选)96 字节 KMIP 密钥数据托管对象的 KMIP 唯一标识符。如果省略此值,Django MongoDB后端将创建一个随机的 96 字节对象。

This code connects to the encrypted medical_records database, stores your data keys in the medical_records.__keyVault collection, and configures your KMS provider.

3

medical_records目录中,创建名为 routers.py 的文件并将以下代码粘贴到其中:

class EncryptedRouter:
def allow_migrate(self, db, app_label, model_name=None, **hints):
# Create medical_records models only in the encrypted database.
if app_label == "medical_records":
return db == "encrypted"
# Don't create collections for other apps in the encrypted db.
if db == "encrypted":
return False
return None
def db_for_read(self, model, **hints):
# All reads and writes for medical_records models go to the encrypted db.
if model._meta.app_label == "medical_records":
return "encrypted"
return None
db_for_write = db_for_read

此文件将 medical_records应用程序中所有模型的数据库操作路由到加密的medical_records数据库。

然后,导航到 settings.py文件并将 DATABASE_ROUTERS 设置替换为以下代码,以添加自定义路由器:

DATABASE_ROUTERS = [
'django_mongodb_backend.routers.MongoRouter',
'medical_records.routers.EncryptedRouter',
]
4

In your medical_records directory, navigate to the models.py file and paste the following code:

from django.db import models
from django_mongodb_backend.models import EmbeddedModel
from django_mongodb_backend.fields import (
EmbeddedModelField,
EncryptedCharField,
EncryptedEmbeddedModelField,
)
class Patient(models.Model):
patient_name = models.CharField(max_length=255)
patient_id = models.BigIntegerField()
patient_record = EmbeddedModelField("PatientRecord")
class Meta:
db_table = "patients"
def __str__(self):
return f"{self.patient_name} ({self.patient_id})"
class PatientRecord(EmbeddedModel):
ssn = EncryptedCharField(max_length=11, queries={"queryType": "equality"})
billing = EncryptedEmbeddedModelField("Billing")
bill_amount = models.DecimalField(max_digits=10, decimal_places=2)
class Billing(EmbeddedModel):
cc_type = models.CharField(max_length=50)
cc_number = models.CharField(max_length=20)

This code creates a Patient model, which corresponds to the patients collection in your medical_records database. It also creates two embedded models, PatientRecord and Billing, to represent nested fields in the collection.

该代码配置以下加密字段:

  • patient_record.ssn:针对相等查询进行加密和配置

  • patient_record.billing.cc_type:已加密,但不可查询

  • patient_record.billing.cc_number:已加密,但不可查询

配置应用程序和数据库连接后,请按照本节中的步骤插入和查询加密文档。

1

django_qe目录运行以下命令,为模型创建迁移并将其应用到数据库:

python manage.py makemigrations medical_records
python manage.py migrate --database encrypted
2

运行以下命令,进入Python Shell。

python manage.py shell

然后,在Shell中运行以下命令以导入所需模型:

from medical_records.models import Patient, PatientRecord, Billing
3

在Shell中运行以下命令,创建 Patient实例,并将相应的加密文档插入数据库:

billing = Billing(cc_type="Visa", cc_number="4111111111111111")
record = PatientRecord(ssn="987-65-4320", billing=billing, bill_amount=1500)
patient = Patient.objects.create(
name="John Doe",
patient_id=12345678,
patient_record=record
)

medical_records.patients如果导航到MongoDB Atlas上的 集合,则可以看到文档的patient_record.ssnpatient_record.billing 字段已加密。

4

运行以下命令,对加密的patient_record.ssn字段执行相等查询:

Patient.objects.get(patient_record__ssn="987-65-4320")

If successful, the command return the following patient data:

<Patient: John Doe (12345678)>

恭喜完成Queryable Encryption教程!您现在拥有一个示例Django应用程序,它使用Queryable Encryption自动加密和解密文档字段。您的应用程序会在服务器端加密敏感数据,并在客户端端查询数据。

要学习;了解有关Queryable Encryption和 Django MongoDB后端的更多信息,请访问以下资源:

后退

事务

在此页面上