2320 字
12 分钟
网络安全基础

网络安全基础#

概述#

网络安全是保护网络系统、数据和用户免受攻击、破坏或未经授权访问的实践。对于前端开发者而言,理解基本的安全概念和防御措施至关重要。

常见安全威胁#

1. 跨站脚本攻击 (XSS)#

XSS 攻击者向网页注入恶意脚本,当其他用户访问该页面时,脚本会在其浏览器中执行。

类型#

  • 存储型 XSS:恶意脚本存储在服务器(如数据库)
  • 反射型 XSS:恶意脚本通过 URL 参数传递
  • DOM 型 XSS:客户端 JavaScript 处理不当导致

防御措施#

// 1. 输入验证与过滤
function sanitizeInput(input) {
  return input
    .replace(/&/g, '&')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;')
    .replace(/\//g, '&#x2F;');
}

// 2. 输出编码
const userInput = '<script>alert("xss")</script>';
const safeOutput = document.createTextNode(userInput);
element.appendChild(safeOutput);

// 3. 使用 Content Security Policy (CSP)
// HTTP 头部
// Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com

现代框架的防护#

// React 自动转义
function App() {
  const userInput = '<script>alert("xss")</script>';
  return <div>{userInput}</div>; // 自动转义,安全
}

// Vue 自动转义
<template>
  <div>{{ userInput }}</div> <!-- 自动转义 -->
</template>

2. 跨站请求伪造 (CSRF)#

CSRF 攻击者诱使用户在已认证的网站上执行非预期的操作。

攻击原理#

1. 用户登录银行网站 (bank.com)
2. 攻击者诱使用户访问恶意网站
3. 恶意网站包含向 bank.com 转账的请求
4. 浏览器自动携带用户的认证 Cookie
5. 银行执行转账操作

防御措施#

// 1. CSRF Token
// 服务器生成 Token,包含在表单中
<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
  <!-- 其他表单字段 -->
</form>

// 服务器验证 Token
app.post('/transfer', (req, res) => {
  const token = req.body.csrf_token;
  if (!validateCsrfToken(token)) {
    return res.status(403).send('CSRF 验证失败');
  }
  // 处理请求
});

// 2. SameSite Cookie
// 设置 Cookie 的 SameSite 属性
Set-Cookie: session=abc123; SameSite=Strict; HttpOnly; Secure

// 3. 验证 Referer/Origin
const referer = req.headers.referer;
const origin = req.headers.origin;
if (!isValidOrigin(referer) || !isValidOrigin(origin)) {
  return res.status(403).send('非法来源');
}

3. SQL 注入#

虽然主要是后端问题,但前端可以协助防御。

防御措施#

// 前端输入验证
function validateEmail(email) {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

// 限制输入长度
<input type="text" maxlength="100" pattern="[A-Za-z0-9@._-]+">

4. 点击劫持 (Clickjacking)#

攻击者使用透明 iframe 覆盖在合法按钮上,诱使用户点击。

防御措施#

// 1. X-Frame-Options 头部
// 禁止页面被嵌入 iframe
X-Frame-Options: DENY
// 或只允许同源
X-Frame-Options: SAMEORIGIN

// 2. Content Security Policy
Content-Security-Policy: frame-ancestors 'self';

// 3. JavaScript 防御
if (window !== window.top) {
  window.top.location = window.location;
}

认证与授权#

1. 认证机制#

// JWT (JSON Web Token) 示例
const jwt = require('jsonwebtoken');

// 生成 Token
const token = jwt.sign(
  { userId: 123, role: 'user' },
  process.env.JWT_SECRET,
  { expiresIn: '24h' }
);

// 验证 Token
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
  if (err) {
    // Token 无效
  } else {
    // Token 有效,decoded 包含用户信息
  }
});

2. 安全存储 Token#

// 安全存储 Token 的示例
class AuthService {
  constructor() {
    this.tokenKey = 'auth_token';
  }

  // 存储 Token
  setToken(token) {
    // 使用 HttpOnly Cookie(更安全)
    document.cookie = `${this.tokenKey}=${token}; HttpOnly; Secure; SameSite=Strict`;
    
    // 或者使用 sessionStorage(页面关闭后清除)
    sessionStorage.setItem(this.tokenKey, token);
  }

  // 获取 Token
  getToken() {
    // 从 Cookie 读取
    const cookies = document.cookie.split(';');
    for (let cookie of cookies) {
      const [name, value] = cookie.trim().split('=');
      if (name === this.tokenKey) return value;
    }
    return null;
  }

  // 清除 Token
  clearToken() {
    document.cookie = `${this.tokenKey}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
    sessionStorage.removeItem(this.tokenKey);
    localStorage.removeItem(this.tokenKey);
  }
}

3. 密码安全#

// 前端密码强度验证
function validatePassword(password) {
  const requirements = {
    minLength: 8,
    hasUpperCase: /[A-Z]/.test(password),
    hasLowerCase: /[a-z]/.test(password),
    hasNumbers: /\d/.test(password),
    hasSpecialChar: /[!@#$%^&*(),.?":{}|<>]/.test(password)
  };

  const score = Object.values(requirements).filter(Boolean).length;
  return {
    isValid: score >= 4 && password.length >= requirements.minLength,
    score: score,
    feedback: generateFeedback(requirements, password.length)
  };
}

// 密码哈希应该在后端进行
// 使用 bcrypt, argon2 等专业库

数据传输安全#

1. HTTPS 强制#

// 前端强制 HTTPS
if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {
  window.location.href = 'https://' + window.location.host + window.location.pathname;
}

// 使用 HSTS (HTTP Strict Transport Security)
// 服务器配置
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

2. 安全头部#

// 重要的安全头部
const securityHeaders = {
  'Content-Security-Policy': "default-src 'self'; script-src 'self'",
  'X-Content-Type-Options': 'nosniff',
  'X-Frame-Options': 'DENY',
  'X-XSS-Protection': '1; mode=block',
  'Referrer-Policy': 'strict-origin-when-cross-origin',
  'Permissions-Policy': 'camera=(), microphone=(), geolocation=()'
};

// Express.js 中间件
app.use((req, res, next) => {
  Object.entries(securityHeaders).forEach(([key, value]) => {
    res.setHeader(key, value);
  });
  next();
});

3. CORS 安全配置#

// 正确的 CORS 配置
const corsOptions = {
  origin: (origin, callback) => {
    const allowedOrigins = [
      'https://example.com',
      'https://www.example.com',
      'http://localhost:3000'
    ];
    
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('CORS 策略阻止此请求'));
    }
  },
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  maxAge: 86400 // 24小时
};

app.use(cors(corsOptions));

第三方资源安全#

1. 子资源完整性 (SRI)#

<!-- 使用 SRI 验证第三方资源 -->
<script 
  src="https://cdn.example.com/jquery@3.6.0.min.js"
  integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We"
  crossorigin="anonymous">
</script>

<link 
  rel="stylesheet" 
  href="https://cdn.example.com/bootstrap@5.1.3/css/bootstrap.min.css"
  integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
  crossorigin="anonymous">

2. 安全加载第三方脚本#

// 安全地加载第三方脚本
function loadScriptSafely(url, attributes = {}) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = url;
    
    // 设置安全属性
    script.crossOrigin = 'anonymous';
    script.referrerPolicy = 'no-referrer';
    
    // 设置自定义属性
    Object.entries(attributes).forEach(([key, value]) => {
      script.setAttribute(key, value);
    });
    
    script.onload = () => resolve(script);
    script.onerror = () => reject(new Error(`加载脚本失败: ${url}`));
    
    document.head.appendChild(script);
  });
}

// 使用示例
loadScriptSafely('https://api.example.com/widget.js', {
  'data-api-key': 'your-api-key'
}).then(() => {
  console.log('脚本加载成功');
}).catch(error => {
  console.error('脚本加载失败:', error);
});

客户端安全#

1. 安全存储#

// 安全存储敏感数据
class SecureStorage {
  constructor() {
    this.storageKey = 'secure_data';
    this.encryptionKey = null;
  }

  // 生成加密密钥(简化示例,实际应使用 Web Crypto API)
  async generateKey() {
    // 使用 Web Crypto API
    const key = await crypto.subtle.generateKey(
      {
        name: 'AES-GCM',
        length: 256
      },
      true,
      ['encrypt', 'decrypt']
    );
    return key;
  }

  // 加密数据
  async encrypt(data) {
    const encoder = new TextEncoder();
    const encoded = encoder.encode(JSON.stringify(data));
    
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encrypted = await crypto.subtle.encrypt(
      {
        name: 'AES-GCM',
        iv: iv
      },
      this.encryptionKey,
      encoded
    );

    return {
      iv: Array.from(iv),
      data: Array.from(new Uint8Array(encrypted))
    };
  }

  // 存储加密数据
  async setSecureData(key, value) {
    const encrypted = await this.encrypt(value);
    localStorage.setItem(key, JSON.stringify(encrypted));
  }

  // 读取解密数据
  async getSecureData(key) {
    const encrypted = JSON.parse(localStorage.getItem(key));
    if (!encrypted) return null;

    const decrypted = await this.decrypt(encrypted);
    return JSON.parse(decrypted);
  }
}

2. 防篡改检测#

// 检测代码是否被篡改
class TamperDetection {
  constructor() {
    this.expectedHashes = {
      'main.js': 'abc123...',
      'app.js': 'def456...'
    };
  }

  // 计算脚本哈希
  async calculateHash(scriptUrl) {
    const response = await fetch(scriptUrl);
    const text = await response.text();
    
    const encoder = new TextEncoder();
    const data = encoder.encode(text);
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
    
    return hashHex;
  }

  // 验证脚本完整性
  async verifyScript(scriptUrl) {
    const actualHash = await this.calculateHash(scriptUrl);
    const expectedHash = this.expectedHashes[scriptUrl];
    
    if (actualHash !== expectedHash) {
      console.error('脚本被篡改:', scriptUrl);
      // 采取相应措施:通知用户、阻止执行等
      return false;
    }
    
    return true;
  }

  // 监控 DOM 变化
  monitorDOM() {
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        // 检查是否添加了可疑脚本
        mutation.addedNodes.forEach((node) => {
          if (node.tagName === 'SCRIPT' && 
              !node.src.startsWith(window.location.origin) &&
              !this.isAllowedThirdParty(node.src)) {
            console.warn('检测到可疑脚本注入:', node.src);
            node.remove();
          }
        });
      });
    });

    observer.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
  }
}

安全测试与监控#

1. 安全测试工具#

// 使用安全扫描工具
// 1. OWASP ZAP - 自动化安全测试
// 2. Burp Suite - 专业安全测试
// 3. Snyk - 依赖漏洞扫描
// 4. npm audit - 检查 npm 包漏洞

// 自动化安全测试脚本
const { exec } = require('child_process');

function runSecurityTests() {
  return new Promise((resolve, reject) => {
    // 运行 npm audit
    exec('npm audit --json', (error, stdout) => {
      const auditResult = JSON.parse(stdout);
      const vulnerabilities = auditResult.metadata.vulnerabilities;
      
      if (vulnerabilities.high > 0 || vulnerabilities.critical > 0) {
        reject(new Error('发现高危漏洞'));
      } else {
        resolve('安全测试通过');
      }
    });
  });
}

2. 安全监控#

// 安全事件监控
class SecurityMonitor {
  constructor() {
    this.events = [];
    this.reportEndpoint = '/api/security/events';
  }

  // 记录安全事件
  logEvent(type, details) {
    const event = {
      type,
      details,
      timestamp: new Date().toISOString(),
      userAgent: navigator.userAgent,
      url: window.location.href,
      referrer: document.referrer
    };

    this.events.push(event);
    
    // 发送到服务器(节流)
    this.throttledReport();
    
    // 控制台警告
    console.warn(`安全事件: ${type}`, details);
  }

  // 节流报告
  throttledReport = _.throttle(() => {
    this.reportEvents();
  }, 5000);

  // 报告事件到服务器
  async reportEvents() {
    if (this.events.length === 0) return;

    const eventsToReport = [...this.events];
    this.events = [];

    try {
      await fetch(this.reportEndpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(eventsToReport)
      });
    } catch (error) {
      // 报告失败,重新加入队列
      this.events.unshift(...eventsToReport);
    }
  }

  // 监控可疑活动
  monitorSuspiciousActivity() {
    // 监控异常表单提交
    document.addEventListener('submit', (event) => {
      const form = event.target;
      const suspiciousFields = form.querySelectorAll('[name*="password"], [name*="token"], [name*="secret"]');
      
      if (suspiciousFields.length > 0 && !form.action.startsWith(window.location.origin)) {
        this.logEvent('suspicious_form_submission', {
          formAction: form.action,
          fields: Array.from(suspiciousFields).map(f => f.name)
        });
      }
    });

    // 监控异常错误
    window.addEventListener('error', (event) => {
      if (event.error && event.error.stack) {
        const stack = event.error.stack;
        if (stack.includes('eval') || stack.includes('Function')) {
          this.logEvent('suspicious_error', {
            message: event.message,
            stack: event.error.stack
          });
        }
      }
    });
  }
}

最佳实践总结#

1. 开发阶段#

  • 使用最新版本的框架和库
  • 定期更新依赖,修复安全漏洞
  • 代码审查时关注安全问题
  • 使用静态代码分析工具

2. 测试阶段#

  • 进行安全测试(XSS、CSRF、SQL 注入等)
  • 使用自动化安全扫描工具
  • 进行渗透测试
  • 测试错误处理和安全边界

3. 部署阶段#

  • 启用 HTTPS 和 HSTS
  • 配置安全 HTTP 头部
  • 限制第三方资源
  • 设置监控和告警

4. 维护阶段#

  • 定期安全审计
  • 监控安全事件
  • 及时响应安全漏洞
  • 保持安全知识更新

安全资源#

1. 学习资源#

  • OWASP Top 10:最重要的安全风险
  • MDN Web 安全文档:浏览器安全特性
  • Security Headers:HTTP 安全头部指南

2. 工具资源#

  • OWASP ZAP:开源安全测试工具
  • Snyk:依赖漏洞扫描
  • Security Headers Scanner:检查安全头部

3. 检查清单#

  • 所有表单都有 CSRF 保护
  • 用户输入都经过验证和转义
  • 使用 HTTPS 和 HSTS
  • 配置安全 HTTP 头部
  • 安全存储敏感数据
  • 限制第三方资源
  • 监控安全事件
  • 定期安全测试

总结#

前端安全是 Web 应用安全的重要组成部分。通过理解常见的安全威胁、实施适当的防御措施、使用安全的开发实践,可以显著降低应用的安全风险。安全是一个持续的过程,需要开发、测试、部署和维护各阶段的共同努力。


创建时间:2026-03-12 分类:前端网络 标签:网络安全, XSS, CSRF, 前端安全, Web安全

网络安全基础
https://ameng404.com/posts/network/网络安全基础/
作者
Ameng
发布于
2026-03-12
许可协议
CC BY-NC-SA 4.0