Skip to content

第 6.5 章:API 安全基础

学习时长: 45 分钟


1. API 安全:空间站的多层防御

想象一下您的空间站 (API) 位于敌对的太空区域。一个力场(身份验证)是远远不够的。您需要一个综合防御系统:

  • 护盾 (HTTPS): 加密所有流量。
  • 异常传感器 (速率限制): 防止过于频繁的请求。
  • 内部隔舱 (授权): 分离访问权限。
  • 货物检查 (验证): 不信任任何传入数据。
  • 秘密保险箱 (环境变量): 安全存储密钥。

让我们来配置每个层面。


2. 护盾:始终使用 HTTPS

这是什么? HTTPS (HyperText Transfer Protocol Secure) 是 HTTP 协议的一个版本,它加密客户端和服务器之间的所有数据。如果没有它,任何“监听”网络的人(例如,在公共 Wi-Fi 中)都可以拦截登录信息、密码和令牌。

如何实现?

  • 在生产环境中 — 必须。 将您的 API 部署到真实服务器(Heroku、DigitalOcean 等)时,配置 Web 服务器(Nginx、Apache)以使用 SSL 证书。Let's Encrypt 等服务提供免费证书。
  • 在本地开发中,这不那么关键,但像 Laravel Herdmkcert 这样的工具可以轻松配置本地 HTTPS。

💡 API 安全第一条规则: 没有 HTTPS — 就没有安全。


3. 异常传感器:速率限制 (Rate Limiting)

这是什么? 防止暴力破解攻击(当攻击者试图通过每秒发送数千个请求来猜测密码时)和 DoS 攻击(当服务器被请求“淹没”以使其停止响应时)。速率限制限制了单个用户(或 IP 地址)在特定时间内可以发出的请求数量。

如何实现?

  • 在 Laravel 中: 速率限制的中间件已经内置! 打开 app/Http/Kernel.php 并查看 middlewareGroups['api'] 键。那里已经有 'throttle:api'。此限制的设置位于 app/Providers/RouteServiceProvider.phpconfigureRateLimiting() 方法中。

    // app/Providers/RouteServiceProvider.php
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });
    }
    
    这意味着:每个用户(如果已授权)或每个 IP 地址每分钟 60 个请求。

  • 在 FastAPI 中: 使用第三方包,例如 slowapi

  • 安装:pip install slowapi

  • main.py 中集成:
    # main.py
    from slowapi import Limiter, _rate_limit_exceeded_handler
    from slowapi.util import get_remote_address
    from slowapi.errors import RateLimitExceeded
    
    limiter = Limiter(key_func=get_remote_address)
    app = FastAPI(...)
    
    # 连接错误处理器和限速器本身
    app.state.limiter = limiter
    app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
    
    # 应用于特定的端点
    @router.get("/planets")
    @limiter.limit("5/minute") # 每分钟 5 个请求
    def get_planets(request: Request):
        # ...
    

4. 内部隔舱:授权(不要与身份验证混淆!)

这是什么?

  • 身份验证 回答“你是谁?”这个问题。
  • 授权 回答“你被允许做什么?”这个问题。

例如,普通用户可以查看行星,但只有具有“管理员”角色的用户才能删除它们。

如何实现?

  • 在 Laravel 中: 使用 Policies(策略)或 Gates(门)。

  • 创建策略:php artisan make:policy PlanetPolicy --model=Planet

  • app/Policies/PlanetPolicy.php 中描述规则:
    class PlanetPolicy
    {
        // 只允许 'admin' 角色的用户删除
        public function delete(User $user, Planet $planet): bool
        {
            return $user->role === 'admin';
        }
    }
    
  • 在控制器 PlanetController.php 中应用策略:

    public function destroy(Planet $planet)
    {
        // 检查当前用户是否有删除权限
        $this->authorize('delete', $planet);
    
        $planet->delete();
        return response()->json(null, 204);
    }
    

  • 在 FastAPI 中: 授权逻辑通常是手动在端点内部编写,使用从令牌中获取的用户信息。

# (假设令牌中有 'roles' 字段)
def get_current_active_user(token: str = Depends(oauth2_scheme)):
    # ... 解码令牌并从数据库获取带有角色的用户
    # user = get_user_from_db(username)
    return user # 返回用户对象

@router.delete("/planets/{planet_id}")
def delete_planet(
    planet_id: int,
    current_user: User = Depends(get_current_active_user)
):
    if "admin" not in current_user.roles:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="没有足够的权限执行此操作",
        )
    # ... 删除逻辑 ...

5. 货物检查和秘密保险箱:验证和环境变量

这两个点我们已经实现过,但重要的是要强调它们在安全中的作用。

  • 永远不要信任传入数据(验证):

  • 我们在 Laravel 中使用了 $request->validate(),在 FastAPI 中使用了 Pydantic 模型。这保护我们免受 SQL 注入(在使用 Eloquent/SQLAlchemy 时)和可能破坏应用程序的不正确数据。始终验证所有来自外部的数据!

  • 将秘密存储在 .env 中(环境变量):

  • 数据库密钥、JWT 的密钥 (SECRET_KEY)、第三方服务密钥 — 所有这些绝不应该进入版本控制系统 (Git)。这就是 .env 文件的作用,它们被添加到 .gitignore 中。


巩固知识小测验

1. 为了防止数据在公共网络中被拦截,应使用:

2. 速率限制 (Rate Limiting) 主要用于防御:

3. 解决“这个用户被允许做什么?”的问题是:

4. API 密钥和数据库密码应存储在:


🚀 课程完成 恭喜您,指挥官!您已成功完成所有任务。

您从一个只听说过 API 的新手,成长为一名能够独立设计、开发、编写文档、保护和测试完整的 Web 服务工程师,并且掌握了其生态系统中最流行的两种技术。

您掌握了通用的 REST 语言,学会了 Laravel 和 FastAPI,并用纯 JavaScript 为它们构建了一个“飞行控制中心”。

这是一个巨大的成就。 API 开发的世界现在向您敞开。继续探索、学习并构建令人惊叹的事物。

通讯结束。 🚀

☄ 支持我们的任务

创建本教程是一次漫长而复杂的飞行,需要大量时间和精力。如果这些材料对您有用,您可以帮助我们补充远征队的燃料箱。 每一次支持都是我们迈向新有用材料的又一个轨道。

Buy Me a Coffee at ko-fi.com