在Django项目开发过程中,前后端环境变量传递是常见需求,比如前端需要获取后端配置的API基础地址、静态资源域名等非敏感配置,或是需要传递用户相关的临时标识。如果处理不当,很容易出现敏感信息泄露、XSS注入等安全问题,因此需要采用合理的方式在Django模板中安全调用JavaScript脚本中的环境变量。

常见的安全风险点
直接在前端暴露环境变量可能存在以下风险:
- 敏感信息泄露:如果将数据库密码、密钥等敏感内容直接写入JavaScript,任何用户都可以通过查看页面源码获取这些信息。
- XSS注入风险:如果环境变量中包含用户输入的内容,未经过转义直接拼接进JavaScript代码,可能被注入恶意脚本。
- 变量解析错误:如果环境变量中包含引号、换行等特殊字符,直接拼接可能导致JavaScript语法错误。
安全实现方案
方案一:使用Django模板过滤器转义后输出
对于非敏感的字符串类型环境变量,可以使用Django内置的escapejs过滤器对变量进行转义,避免特殊字符导致的语法问题或注入风险。
首先在Django的视图函数中将环境变量传递到模板上下文:
# views.py
from django.shortcuts import render
import os
def index_view(request):
context = {
# 非敏感的环境变量,比如API基础地址
"api_base_url": os.getenv("API_BASE_URL", "https://ipipp.com/api"),
# 用户相关的非敏感标识
"user_id": request.user.id if request.user.is_authenticated else ""
}
return render(request, "index.html", context)
然后在模板中通过escapejs过滤器输出变量到JavaScript中:
<script>
// 使用escapejs过滤器转义变量,避免特殊字符问题
const apiBaseUrl = "{{ api_base_url|escapejs }}";
const userId = "{{ user_id|escapejs }}";
console.log("API地址:", apiBaseUrl);
console.log("用户ID:", userId);
</script>
方案二:使用JSON序列化传递复杂类型变量
如果需要传递对象、数组等复杂类型的环境变量,直接使用字符串拼接容易出现格式错误,此时可以先将变量序列化为JSON字符串,再通过safe过滤器输出,同时注意对JSON中的特殊字符进行处理。
视图函数中构造复杂类型的环境变量:
# views.py
import json
from django.shortcuts import render
import os
def index_view(request):
env_config = {
"api_base_url": os.getenv("API_BASE_URL", "https://ipipp.com/api"),
"static_domain": os.getenv("STATIC_DOMAIN", "https://ipipp.com/static"),
"feature_flags": {
"enable_comment": True,
"enable_upload": False
}
}
# 将字典序列化为JSON字符串
context = {
"env_config_json": json.dumps(env_config)
}
return render(request, "index.html", context)
模板中解析JSON字符串获取环境变量:
<script>
// 先通过escapejs处理JSON字符串中的特殊字符,再解析为对象
const envConfigStr = "{{ env_config_json|escapejs }}";
try {
const envConfig = JSON.parse(envConfigStr);
console.log("环境配置:", envConfig);
console.log("功能开关:", envConfig.feature_flags);
} catch (e) {
console.error("环境变量解析失败:", e);
}
</script>
方案三:通过隐藏域传递环境变量
如果不想在JavaScript代码中直接嵌入模板变量,也可以通过HTML隐藏域存储环境变量,再由JavaScript读取,这种方式可以进一步降低变量被直接篡改的风险。
模板中添加隐藏域:
<!-- 隐藏域存储环境变量,使用data-前缀自定义属性 -->
<input type="hidden" id="env-config"
data-api-url="{{ api_base_url|escapejs }}"
data-user-id="{{ user_id|escapejs }}"
data-static-domain="{{ static_domain|escapejs }}"
>
JavaScript中读取隐藏域的属性:
// 读取隐藏域的环境变量
const envInput = document.getElementById("env-config");
const apiUrl = envInput.dataset.apiUrl;
const userId = envInput.dataset.userId;
const staticDomain = envInput.dataset.staticDomain;
console.log("从隐藏域获取的配置:", { apiUrl, userId, staticDomain });
安全注意事项
- 禁止传递敏感信息:数据库密码、密钥、私密Token等敏感内容绝对不能传递到前端JavaScript中,即使做了转义也存在泄露风险。
- 始终使用转义:所有从后端传递到前端的变量,只要是要嵌入JavaScript代码的,都必须使用
escapejs或对应的转义处理,避免XSS攻击。 - 校验变量合法性:前端获取到环境变量后,建议对变量格式、内容进行校验,避免使用被篡改的非法值。
- 最小化传递范围:只传递前端真正需要的环境变量,不要将后端所有的环境变量都暴露到前端。
方案选择建议
如果只需要传递少量简单的字符串变量,优先选择方案一,实现简单且安全;如果需要传递对象、数组等复杂结构,选择方案二,通过JSON序列化可以减少格式错误;如果对安全性要求更高,或者需要避免JavaScript代码中直接出现模板变量,选择方案三的隐藏域方式。
DjangoJavaScript环境变量模板安全修改时间:2026-07-11 09:33:14