🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx @anthropic-ai/skills install supercent-io/skills-template/security-best-practices

💡 提示:需要 Node.js 和 NPM

安全最佳实践

何时使用此技能

  • 新项目:从一开始就考虑安全性
  • 安全审计:检查和修复漏洞
  • 公共 API:强化可对外访问的 API
  • 合规性:遵守 GDPR、PCI-DSS 等法规

指示

步骤 1:强制使用 HTTPS 和安全头部

Express.js 安全中间件

import express from 'express';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';

const app = express();

// Helmet:自动设置安全头部
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'unsafe-inline'", "https://trusted-cdn.com"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
      connectSrc: ["'self'", "https://api.example.com"],
      fontSrc: ["'self'", "https:", "data:"],
      objectSrc: ["'none'"],
      mediaSrc: ["'self'"],
      frameSrc: ["'none'"],
    },
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  }
}));

// 强制使用 HTTPS
app.use((req, res, next) => {
  if (process.env.NODE_ENV === 'production' && !req.secure) {
    return res.redirect(301, `https://${req.headers.host}${req.url}`);
  }
  next();
});

// 速率限制(DDoS 防护)
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 分钟
  max: 100, // 每个 IP 最多 100 次请求
  message: '来自此 IP 的请求过多,请稍后再试。',
  standardHeaders: true,
  legacyHeaders: false,
});

app.use('/api/', limiter);

// 对认证端点实施更严格的限制
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5, // 每 15 分钟仅 5 次
  skipSuccessfulRequests: true // 不计数成功请求
});

app.use('/api/auth/login', authLimiter);

步骤 2:输入验证(防止 SQL 注入、XSS)

Joi 验证

import Joi from 'joi';

const userSchema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(8).pattern(/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/).required(),
  name: Joi.string().min(2).max(50).required()
});

app.post('/api/users', async (req, res) => {
  // 1. 验证输入
  const { error, value } = userSchema.validate(req.body);

  if (error) {
    return res.status(400).json({ error: error.details[0].message });
  }

  // 2. 防止 SQL 注入:参数化查询
  // ❌ 反面示例
  // db.query(`SELECT * FROM users WHERE email = '${email}'`);

  // ✅ 正确示例
  const user = await db.query('SELECT * FROM users WHERE email = ?', [value.email]);

  // 3. 防止 XSS:输出编码
  // React/Vue 会自动转义;否则请使用库
  import DOMPurify from 'isomorphic-dompurify';
  const sanitized = DOMPurify.sanitize(userInput);

  res.json({ user: sanitized });
});

步骤 3:防止 CSRF

CSRF 令牌

import csrf from 'csurf';
import cookieParser from 'cookie-parser';

app.use(cookieParser());

// CSRF 防护
const csrfProtection = csrf({ cookie: true });

// 提供 CSRF 令牌
app.get('/api/csrf-token', csrfProtection, (req, res) => {
  res.json({ csrfToken: req.csrfToken() });
});

// 在所有 POST/PUT/DELETE 请求上验证 CSRF
app.post('/api/*', csrfProtection, (req, res, next) => {
  next();
});

// 在客户端使用
// fetch('/api/users', {
//   method: 'POST',
//   headers: {
//     'CSRF-Token': csrfToken
//   },
//   body: JSON.stringify(data)
// });

步骤 4:管理密钥

.env(切勿提交)

# 数据库
DATABASE_URL=postgresql://user:password@localhost:5432/mydb

# JWT
ACCESS_TOKEN_SECRET=your-super-secret-access-token-key-min-32-chars
REFRESH_TOKEN_SECRET=your-super-secret-refresh-token-key-min-32-chars

# API 密钥
STRIPE_SECRET_KEY=sk_test_xxx
SENDGRID_API_KEY=SG.xxx

Kubernetes 密钥

apiVersion: v1
kind: Secret
metadata:
  name: myapp-secrets
type: Opaque
stringData:
  database-url: postgresql://user:password@postgres:5432/mydb
  jwt-secret: your-jwt-secret
// 从环境变量读取
const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) {
  throw new Error('需要设置 DATABASE_URL 环境变量');
}

步骤 5:安全的 API 认证

JWT + 刷新令牌轮换

// 短生命周期访问令牌(15 分钟)
const accessToken = jwt.sign({ userId }, ACCESS_SECRET, { expiresIn: '15m' });

// 长生命周期刷新令牌(7 天),存储在数据库中
const refreshToken = jwt.sign({ userId }, REFRESH_SECRET, { expiresIn: '7d' });
await db.refreshToken.create({
  userId,
  token: refreshToken,
  expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
});

// 刷新令牌轮换:每次使用时重新发放
app.post('/api/auth/refresh', async (req, res) => {
  const { refreshToken } = req.body;

  const payload = jwt.verify(refreshToken, REFRESH_SECRET);

  // 使现有令牌失效
  await db.refreshToken.delete({ where: { token: refreshToken } });

  // 发放新令牌
  const newAccessToken = jwt.sign({ userId: payload.userId }, ACCESS_SECRET, { expiresIn: '15m' });
  const newRefreshToken = jwt.sign({ userId: payload.userId }, REFRESH_SECRET, { expiresIn: '7d' });

  await db.refreshToken.create({
    userId: payload.userId,
    token: newRefreshToken,
    expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
  });

  res.json({ accessToken: newAccessToken, refreshToken: newRefreshToken });
});

约束条件

必需规则(必须遵守)

  1. 仅 HTTPS:生产环境必须使用 HTTPS
  2. 密钥分离:通过环境变量管理;切勿硬编码在代码中
  3. 输入验证:验证所有用户输入
  4. 参数化查询:防止 SQL 注入
  5. 速率限制:防止 DDoS 攻击

禁止事项(不得违反)

  1. 不使用 eval():存在代码注入风险
  2. 不直接使用 innerHTML:存在 XSS 风险
  3. 不提交密钥:切勿提交 .env 文件

OWASP Top 10 检查清单

- [ ] A01:访问控制失效 - 基于角色的访问控制、授权检查
- [ ] A02:加密失败 - HTTPS、加密
- [ ] A03:注入 - 参数化查询、输入验证
- [ ] A04:不安全设计 - 安全设计原则
- [ ] A05:安全配置错误 - Helmet、更改默认密码
- [ ] A06:易受攻击的组件 - npm audit、定期更新
- [ ] A07:认证失败 - 强认证、多因素认证
- [ ] A08:数据完整性失败 - 签名验证、CSRF 防护
- [ ] A09:日志记录失败 - 安全事件日志记录
- [ ] A10:服务端请求伪造 - 验证出站请求

最佳实践

  1. 最小权限原则:授予最小必要权限
  2. 纵深防御:多层安全防护
  3. 安全审计:定期进行安全审查

参考资料

元数据

版本

  • 当前版本:1.0.0
  • 最后更新:2025-01-01
  • 兼容平台:Claude, ChatGPT, Gemini

相关技能

标签

#安全 #OWASP #HTTPS #CORS #XSS #SQL注入 #CSRF #基础设施

示例

示例 1:基本用法

示例 2:高级用法

📄 原始文档

完整文档(英文):

https://skills.sh/supercent-io/skills-template/security-best-practices

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。