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

如何隐藏Django传递给JS的变量,避免其出现在页面源码中?

解决Django模板传递数据暴露在页面源码的问题

我完全懂你的困扰——把后端数据直接通过{{ }}注入到页面脚本里,确实会让原始数据明明白白出现在Chrome的Elements面板里,要是涉及敏感信息的话风险不小。下面几个方案可以帮你解决这个问题,按推荐程度排序:


1. 优先选择:通过AJAX动态从API获取数据

这是最符合你RESTful API架构的方案,也从根源上避免了数据出现在页面源码里。思路很简单:页面加载后,用JS/JQuery主动发起请求到你的Django接口,拿到数据再构建UI,而不是一开始就把数据塞到模板里。

具体步骤:

  • 第一步:在Django里写一个返回JSON的视图
    把你生成df_dict和names的逻辑移到一个专门的API视图里,用JsonResponse返回数据:

    from django.http import JsonResponse
    from django.views.decorators.http import require_GET
    import json
    
    @require_GET
    def fetch_ui_data(request):
        # 这里换成你实际生成df_dict和names的代码
        df_dict = {"sample_key": "sample_value"}
        names = ["Alice", "Bob", "Charlie"]
        # 返回结构化JSON
        return JsonResponse({
            "df_dict": df_dict,
            "names": names
        })
    

    记得在urls.py里给这个视图配置路由,比如path("api/ui-data/", fetch_ui_data, name="fetch_ui_data")

  • 第二步:修改前端脚本,动态请求数据
    把原来直接用模板变量的代码改成页面加载后发请求:

    $(document).ready(function() {
        // 发起GET请求到刚写的API接口
        $.get("/api/ui-data/", function(response) {
            // 拿到数据后再构建下拉框和按钮
            const dfDict = response.df_dict;
            const names = response.names;
    
            // 示例:构建下拉选择框
            const select = $("#name-select");
            names.forEach(name => {
                select.append(`<option value="${name}">${name}</option>`);
            });
    
            // 这里继续写你的数据展示逻辑
        });
    });
    

优点:

  • 数据完全不会出现在页面源码里,只会在网络请求的响应里可见(如果需要更安全,可以给这个接口加登录验证或者权限控制)
  • 符合RESTful的设计理念,数据和视图解耦,后续维护更方便

2. 备选方案:加密模板传递的变量

如果因为某些限制必须从模板传递数据(比如不想额外加API接口),可以先在后端加密数据,前端拿到后解密再使用。这样页面源码里只会显示加密后的字符串,不会暴露原始数据。

具体步骤:

  • 第一步:后端加密数据
    用AES之类的对称加密算法把数据加密后传到模板,这里以pycryptodome库为例:

    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    import base64
    import json
    
    # 注意:密钥要保密,建议存在环境变量里,不要硬编码
    AES_KEY = b'your-16-or-32-byte-key' # AES-128用16位,AES-256用32位
    cipher = AES.new(AES_KEY, AES.MODE_CBC)
    
    # 把要传递的数据转成JSON字符串
    data_to_encrypt = json.dumps({
        "df_dict": df_dict,
        "names": names
    }).encode('utf-8')
    # 加密并转成Base64方便在模板里传递
    encrypted_data = base64.b64encode(cipher.encrypt(pad(data_to_encrypt, AES.block_size))).decode('utf-8')
    # 把IV(初始化向量)也传到前端,解密需要用
    iv = base64.b64encode(cipher.iv).decode('utf-8')
    
    # 把加密后的数据和IV放到context里
    context['encrypted_data'] = encrypted_data
    context['iv'] = iv
    
  • 第二步:前端解密数据
    用crypto-js库(可通过npm安装后引入本地文件,或下载源码到项目中)解密拿到原始数据:

    <!-- 先引入本地的crypto-js文件 -->
    <script src="/static/js/crypto-js.min.js"></script>
    
    <script>
    $(document).ready(function() {
        // 从模板拿到加密数据和IV
        const encryptedData = "{{ encrypted_data }}";
        const iv = "{{ iv }}";
        // 密钥要和后端一致
        const key = CryptoJS.enc.Utf8.parse('your-16-or-32-byte-key');
        const ivParsed = CryptoJS.enc.Base64.parse(iv);
    
        // 解密并转成JSON对象
        const decryptedBytes = CryptoJS.AES.decrypt(encryptedData, key, { iv: ivParsed });
        const rawData = JSON.parse(decryptedBytes.toString(CryptoJS.enc.Utf8));
    
        const dfDict = rawData.df_dict;
        const names = rawData.names;
        // 继续构建UI逻辑
    });
    </script>
    

注意事项:

  • 密钥一定要保管好,不能泄露,建议用环境变量管理,不要硬编码在代码里
  • 这种方式只是隐藏原始数据,加密后的内容还是会出现在源码里,适合非极度敏感但不想直接暴露的数据

为什么之前的display:none没用?

你之前尝试给脚本加ID再用CSS隐藏,其实是误解了——<script>标签本身的内容不管怎么设置display:none,都会出现在Elements面板里,因为CSS隐藏的是元素的渲染效果,而不是元素本身的内容。脚本的内容属于DOM的一部分,浏览器会解析它,所以必然会在Elements里显示。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:04:24