全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 10 分钟 ✍️ juanwangdev

安全编码实践

安全编码从开发源头规避漏洞,比事后修补更高效可靠。

变量与作用域安全

避免全局变量污染

JavaScript
// 不安全:全局变量污染
var userData = {};
function processUser() {}

// 安全:使用IIFE或模块
const UserModule = (function() {
  const userData = {}; // 私有变量

  return {
    processUser() {
      // 处理逻辑
    }
  };
})();

// 更佳:ES模块
// userModule.js
const userData = new WeakMap();

export function processUser(user) {
  // 模块作用域内安全访问
}

变量提升陷阱

JavaScript
// 危险:var提升导致意外行为
function init() {
  if (false) {
    var sensitive = 'data'; // 仍被提升
  }
  console.log(sensitive); // undefined,变量已存在
}

// 安全:使用let/const
function init() {
  if (false) {
    const sensitive = 'data'; // 块级作用域
  }
  console.log(sensitive); // ReferenceError
}

敏感数据保护

JavaScript
// 不安全:敏感信息暴露
const API_KEY = 'sk-1234567890'; // 可被遍历访问

// 安全:使用闭包保护
const createAPI = (function() {
  const key = process.env.API_KEY; // 环境变量

  return {
    call(endpoint) {
      return fetch(endpoint, {
        headers: { 'Authorization': `Bearer ${key}` }
      });
    }
  };
})();

// 更佳:WeakMap存储私有数据
const privateData = new WeakMap();

class SecureObject {
  constructor(secret) {
    privateData.set(this, { secret });
  }

  getSecret() {
    return privateData.get(this).secret;
  }
}

函数安全实践

参数验证

JavaScript
// 不安全:无参数验证
function transfer(from, to, amount) {
  accounts[from] -= amount;
  accounts[to] += amount;
}

// 安全:严格参数验证
function transfer(from, to, amount) {
  // 类型检查
  if (typeof from !== 'string' || typeof to !== 'string') {
    throw new TypeError('账户必须是字符串');
  }

  // 数值安全检查
  if (!Number.isFinite(amount) || amount <= 0) {
    throw new RangeError('金额必须为正数');
  }

  // 边界检查
  if (amount > MAX_TRANSFER) {
    throw new Error('超出转账限额');
  }

  // 执行操作
  accounts[from] -= amount;
  accounts[to] += amount;
}

避免隐式类型转换

JavaScript
// 危险:隐式转换导致安全问题
if (userInput == 'admin') { // '123' == 'admin' 为 false,但 1 == '1' 为 true
  grantAccess();
}

// 安全:严格相等
if (userInput === 'admin') {
  grantAccess();
}

// 更安全:类型先验证
if (typeof userInput === 'string' && userInput === 'admin') {
  grantAccess();
}

防止原型污染

JavaScript
// 危险:原型污染
function merge(target, source) {
  for (const key in source) {
    target[key] = source[key];
  }
}

merge({}, JSON.parse('{"__proto__":{"admin":true}}'));
// 所有对象被污染

// 安全:Object.create(null)或hasOwnProperty检查
function safeMerge(target, source) {
  for (const key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      target[key] = source[key];
    }
  }
  return target;
}

// 更佳:使用Object.assign或展开运算符
const merged = { ...target, ...source };

异步代码安全

错误处理

JavaScript
// 不安全:未处理Promise拒绝
async function fetchData() {
  const response = await fetch(url);
  return response.json(); // 可能抛出异常
}

// 安全:完整错误处理
async function fetchData() {
  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('请求失败:', error.message);
    throw error; // 或返回默认值
  }
}

竞态条件防护

JavaScript
// 危险:竞态条件
let lastResult = null;

async function search(query) {
  const results = await fetch(`/search?q=${query}`);
  lastResult = results; // 可能被后续请求覆盖
  render(lastResult);
}

// 安全:请求标识或取消
let searchId = 0;

async function search(query) {
  const currentId = ++searchId;
  const results = await fetch(`/search?q=${query}`);

  if (currentId === searchId) {
    render(results); // 只渲染最新请求
  }
}

// 更佳:AbortController取消
const controller = new AbortController();

async function search(query) {
  controller.abort(); // 取消前一个请求

  try {
    const results = await fetch(`/search?q=${query}`, {
      signal: controller.signal
    });
    render(results);
  } catch (error) {
    if (error.name !== 'AbortError') {
      throw error;
    }
  }
}

安全配置与工具

CSP内容安全策略

JavaScript
// Express设置CSP头
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; " +
    "script-src 'self' 'nonce-abc123'; " +
    "style-src 'self' 'unsafe-inline'; " +
    "img-src 'self' data: https:;"
  );
  next();
});

环境变量管理

JavaScript
// 不安全:硬编码配置
const dbPassword = 'password123';

// 安全:环境变量
const dbPassword = process.env.DB_PASSWORD;

// 更安全:配置验证
const config = {
  db: {
    host: process.env.DB_HOST || 'localhost',
    password: (() => {
      if (!process.env.DB_PASSWORD) {
        throw new Error('DB_PASSWORD未配置');
      }
      return process.env.DB_PASSWORD;
    })()
  }
};

依赖安全检查

Bash
# 检查已知漏洞
npm audit

# 自动修复
npm audit fix

# 使用更严格的包管理器
npm ci  # 使用lockfile确保一致性

代码审查清单

检查项安全要求
变量声明使用const/let,避免var
全局变量最小化,使用模块封装
参数验证类型、范围、边界检查
错误处理try-catch覆盖所有异步操作
敏感数据不硬编码,使用环境变量
原型操作禁止修改Object.prototype
正则表达式避免ReDoS,限制回溯

要点总结

核心原则

  • 最小权限原则:变量、函数、模块最小暴露
  • 深度防御:多层验证,不依赖单一防护
  • 安全默认:默认拒绝,显式允许
  • 输入不信任:所有外部数据验证后才使用

实践要点

  • 使用const/let替代var
  • 所有函数参数必须验证
  • 敏感配置使用环境变量
  • 异步代码必须有错误处理
  • 定期进行依赖安全审计

📝 发现内容有误?点击此处直接编辑

← 上一篇 V8 引擎内部机制
下一篇 → 跨站脚本攻击(XSS)防御
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库