You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django项目中使用openpyxl给Excel加密码保护不生效问题求助

问题排查与修复方案

核心问题点

  • 混淆了工作簿级保护和工作表级保护的赋值对象,WorkbookProtection是工作簿级配置,应该赋值给workbook.security属性,而非worksheet.protection
  • openpyxl本身不支持设置Excel文件的打开密码(即整个文件加密必须输入密码才能查看),它仅支持两类保护:
    • 工作簿结构保护:禁止新增/删除/重命名工作表
    • 工作表编辑保护:禁止修改工作表的单元格内容、格式等
  • 当前保护配置参数绑定对象错误,导致配置完全未生效

修复代码示例

场景1:仅保护工作簿结构(禁止修改工作表数量、名称等)

def export_member_to_xlsx(request):
    from openpyxl.workbook.protection import WorkbookProtection
    import datetime
    from django.contrib.auth.models import User
    from django.http import HttpResponse
    from openpyxl import Workbook

    user_queryset = User.objects.filter(is_staff=False)

    response = HttpResponse(
        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    )
    response['Content-Disposition'] = 'attachment; filename={date}-members.xlsx'.format(
        date=datetime.datetime.now().strftime('%Y-%m-%d'),
    )
    workbook = Workbook()
    # 工作簿保护正确绑定到workbook的security属性
    workbook.security = WorkbookProtection(workbookPassword='password', lockStructure=True)
    
    worksheet = workbook.active
    worksheet.title = 'Members'
    columns = [
        'User',
        'Email',
        'First Name',
        'Last Name',
        'Member Since',
        'Subscription Expiry',
    ]
    row_num = 1
    for col_num, column_title in enumerate(columns, 1):
        cell = worksheet.cell(row=row_num, column=col_num)
        cell.value = column_title
    for member in user_queryset:
        row_num += 1
        row = [
            member.username,
            member.email,
            member.first_name,
            member.last_name,
            member.date_joined,
            # 请自行确保subscriptions关联逻辑正确,此处保留原有写法
            member.subscriptions.current_period_end,
        ]
        for col_num, cell_value in enumerate(row, 1):
            cell = worksheet.cell(row=row_num, column=col_num)
            cell.value = cell_value
    workbook.save(response)
    return response

场景2:保护工作表禁止编辑内容

如果需要禁止用户修改工作表内的单元格内容,使用工作表保护配置即可:

# 省略其他相同逻辑,仅修改worksheet配置部分
worksheet = workbook.active
worksheet.title = 'Members'
# 工作表保护配置
worksheet.protection.password = 'password'
worksheet.protection.enable()  # 开启保护
# 可单独配置允许的操作,比如允许用户筛选内容:
# worksheet.protection.autoFilter = False

场景3:需要设置整个文件的打开密码

如果需要用户必须输入密码才能打开查看整个Excel文件,openpyxl无法直接实现,你可以借助msoffcrypto-tool在生成xlsx文件后二次加密,示例逻辑如下:

# 先将openpyxl生成的文件写入临时内存
from io import BytesIO
import msoffcrypto

temp = BytesIO()
workbook.save(temp)
temp.seek(0)

# 加密文件
encrypted = BytesIO()
file = msoffcrypto.OfficeFile(temp)
file.load_key(password='password')
file.encrypt(encrypted)
encrypted.seek(0)

# 替换HttpResponse的内容
response.write(encrypted.getvalue())

注意事项

  • 工作簿结构保护和工作表保护的密码都可以被简单工具绕过,仅用于防止普通用户误操作,不能用于敏感数据加密
  • 若需要高安全性的加密,建议生成文件后打包为加密压缩包再提供下载

内容的提问来源于stack exchange,提问作者Biju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:54:07