Web 安全防护教程 — 开发者必知必会

适用人群:所有Web开发者
学习时长:约1天
重要程度:★★★★★(安全是底线)

一、常见Web攻击

攻击类型说明危害等级
SQL注入通过SQL语句注入获取数据★★★★★
XSS跨站脚本攻击★★★★☆
CSRF跨站请求伪造★★★★☆
文件上传漏洞上传恶意文件★★★★☆
暴力破解穷举密码★★★☆☆
中间人攻击窃取传输数据★★★★☆

二、SQL注入防护

2.1 攻击示例

-- 原始SQL
SELECT * FROM users WHERE username = 'admin' AND password = '123456'

-- 注入攻击
-- 用户输入:admin' OR '1'='1
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = ''
-- 结果:绕过登录,获取所有用户

2.2 防护方法

// PHP - 使用预处理语句(PDO)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$username, $password]);
$user = $stmt->fetch();

// Laravel
$user = User::where('username', $username)->where('password', $password)->first();

// ThinkPHP
$user = User::where('username', $username)->where('password', $password)->find();

# Python - SQLAlchemy
user = User.query.filter_by(username=username, password=password).first()

# Flask - 参数化查询
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))

// Node.js - Prisma
const user = await prisma.user.findUnique({
  where: { username: username }
})

// 参数化查询
db.query("SELECT * FROM users WHERE username = ?", [username])


三、XSS防护

3.1 攻击类型

反射型XSS:恶意脚本通过URL参数注入
存储型XSS:恶意脚本存入数据库
DOM型XSS:前端JS直接操作DOM

3.2 防护方法

<!-- 1. 输出转义 -->
<!-- PHP -->
<?= htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8') ?>

<!-- Vue.js(自动转义) -->
<template>
  <div>{{ userInput }}</div>  <!-- 自动转义 -->
  <div v-html="sanitizedHtml"></div>  <!-- 需要手动清理 -->
</template>

<!-- React(自动转义) -->
<div>{userInput}</div>  <!-- 自动转义 -->

// 2. Content Security Policy (CSP)
// Nginx配置
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';";

// 3. 输入验证
function sanitizeInput(input) {
  return input
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;')
}


四、CSRF防护

4.1 攻击原理

1. 用户登录银行网站,获取Cookie
2. 用户访问恶意网站
3. 恶意网站自动发送请求到银行网站
4. 浏览器自动携带Cookie,请求成功

4.2 防护方法

// Laravel - CSRF Token
// 表单中添加
@csrf

// 中间件验证
Route::middleware('csrf')->group(function () {
    // ...
});

// API使用Sanctum
Route::middleware('auth:sanctum')->group(function () {
    // ...
});

# Flask - CSRF保护
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)

# 表单中添加
<form method="POST">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
</form>

# Nginx - SameSite Cookie
add_header Set-Cookie "key=value; SameSite=Strict; Secure; HttpOnly";


五、认证安全

5.1 密码安全

// PHP - 密码加密
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// 验证
if (password_verify($inputPassword, $hashedPassword)) {
    // 密码正确
}

// Laravel
Hash::make($password)
Hash::check($inputPassword, $hashedPassword)

# Python - Werkzeug
from werkzeug.security import generate_password_hash, check_password_hash

hashed = generate_password_hash(password)
check_password_hash(hashed, input_password)

5.2 JWT安全

// JWT最佳实践
const jwt = require('jsonwebtoken')

// 生成Token
const token = jwt.sign(
  { userId: user.id, role: user.role },
  SECRET_KEY,
  { expiresIn: '24h' }  // 设置过期时间
)

// 验证Token
try {
  const decoded = jwt.verify(token, SECRET_KEY)
  // Token有效
} catch (err) {
  // Token无效或过期
}

5.3 限流防暴力破解

# Nginx限流
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

server {
    location /api/auth/login {
        limit_req zone=login burst=3 nodelay;
        proxy_pass http://backend;
    }
}

// Laravel限流
Route::middleware('throttle:5,1')->group(function () {
    Route::post('/login', [AuthController::class, 'login']);
});


六、文件上传安全

// Laravel - 文件验证
$request->validate([
    'file' => 'required|file|max:10240|mimes:jpg,png,pdf',
]);

// 存储到非Web目录
$path = $request->file('file')->store('uploads', 'local');

// 生成随机文件名
$filename = uniqid() . '.' . $request->file('extension');

# Flask - 文件上传
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'pdf'}

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['file']
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))


七、HTTPS配置

# Nginx HTTPS配置
server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /etc/ssl/certs/example.com.pem;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # HSTS
    add_header Strict-Transport-Security "max-age=63072000" always;
}

# HTTP跳转HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}


八、安全头配置

# Nginx安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self';" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;


九、安全检查清单

输入验证
✅ 所有用户输入都需要验证
✅ 白名单验证优于黑名单验证
✅ 长度限制、类型限制、格式验证

输出编码
✅ HTML输出转义
✅ JavaScript输出转义
✅ URL参数编码
✅ SQL参数化查询

认证安全
✅ 密码加密存储(bcrypt/argon2)
✅ JWT设置过期时间
✅ 登录失败限流
✅ 敏感操作二次验证

传输安全
✅ 全站HTTPS
✅ HSTS启用
✅ Cookie设置Secure和HttpOnly

文件安全
✅ 文件类型白名单验证
✅ 文件大小限制
✅ 随机文件名
✅ 存储到非Web目录

配置安全
✅ 关闭调试模式
✅ 删除默认页面
✅ 最小权限原则
✅ 定期更新依赖


学习建议

  1. 理解OWASP Top 10,这是最常见的Web安全风险
  2. 所有输入都要验证,不要信任任何用户输入
  3. 使用框架的安全功能,如Laravel的CSRF保护
  4. 定期更新依赖,修复已知漏洞
  5. 安全意识比技术更重要,时刻保持警惕
返回首页