You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅允许指定前端域名访问FastAPI RESTful服务?

解决方案:限制FastAPI后端仅响应Angular前端请求

核心思路

你的服务面向公众且无登录体系,核心目标是区分浏览器合法前端请求与模拟/爬虫请求,不能仅依赖易伪造的基础请求头,需结合浏览器原生安全机制构建多层校验。

可行方案

1. 严格配置CORS策略

用FastAPI的CORSMiddleware仅允许前端域名,阻断浏览器层面的非法跨域请求:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://w.domain.com"],  # 仅开放前端域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
    max_age=3600,
)

注:此方法仅拦截浏览器跨域,无法阻止curl这类直接发起的请求,需配合其他校验。

2. 校验Origin头+处理预检请求

浏览器跨域请求会自动携带Origin头,后端可在中间件中校验该值,并正确响应OPTIONS预检请求:

from fastapi import Request, HTTPException
from starlette.middleware.base import BaseHTTPMiddleware

class OriginCheckMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        allowed_origin = "https://w.domain.com"
        origin = request.headers.get("origin")

        # 处理浏览器预检请求
        if request.method == "OPTIONS":
            response = await call_next(request)
            response.headers["Access-Control-Allow-Origin"] = allowed_origin
            response.headers["Access-Control-Allow-Credentials"] = "true"
            return response
        
        # 非预检请求校验Origin
        if origin != allowed_origin:
            raise HTTPException(status_code=403, detail="非法请求来源")
        
        response = await call_next(request)
        response.headers["Access-Control-Allow-Origin"] = allowed_origin
        return response

app.add_middleware(OriginCheckMiddleware)

curl可伪造Origin,但配合下方方案能进一步过滤。

3. 校验浏览器专属Sec-Fetch-*头

浏览器会自动添加Sec-Fetch-*系列请求头,这些头无法通过前端JS修改,仅由浏览器生成:

  • Sec-Fetch-Site: 跨域场景下取值为cross-site
  • Sec-Fetch-Mode: 跨域请求取值为cors

在中间件中加入校验逻辑:

# 延续上面的OriginCheckMiddleware,在Origin校验后添加
sec_fetch_site = request.headers.get("sec-fetch-site")
sec_fetch_mode = request.headers.get("sec-fetch-mode")

if sec_fetch_site not in ["cross-site", "same-site"] or sec_fetch_mode != "cors":
    raise HTTPException(status_code=403, detail="非合法浏览器请求")

普通用户很难知晓这些头的正确取值,能过滤大部分非浏览器发起的恶意请求。

4. 短时效临时Token验证(无登录场景)

Angular前端初始化时向后端请求一个5分钟有效期的临时Token,后续所有API请求携带该Token:

  • 前端Angular代码示例:
// 获取临时Token
async getTempToken(): Promise<string> {
  const res = await fetch('https://r.domain.com/api/temp-token', {
    method: 'GET',
    credentials: 'include'
  });
  const data = await res.json();
  return data.token;
}

// 携带Token发起请求
async fetchApiData() {
  const token = await this.getTempToken();
  const res = await fetch('https://r.domain.com/api/data', {
    headers: { 'X-Temp-Token': token }
  });
  // 处理响应逻辑
}
  • 后端FastAPI代码示例:
from fastapi import Depends, HTTPException
from jose import JWTError, jwt
from datetime import datetime, timedelta

SECRET_KEY = "your-custom-secret-key"
ALGORITHM = "HS256"
TOKEN_EXPIRE_MINUTES = 5

def generate_temp_token():
    expire = datetime.utcnow() + timedelta(minutes=TOKEN_EXPIRE_MINUTES)
    encoded_jwt = jwt.encode({"exp": expire}, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

@app.get("/api/temp-token")
async def issue_temp_token(request: Request):
    # 先校验Origin和Sec-Fetch头,确保是合法浏览器请求
    origin = request.headers.get("origin")
    if origin != "https://w.domain.com":
        raise HTTPException(status_code=403)
    return {"token": generate_temp_token()}

def validate_temp_token(token: str = Depends(...)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        if datetime.fromtimestamp(payload["exp"]) < datetime.utcnow():
            raise HTTPException(status_code=401, detail="Token已过期")
        return payload
    except JWTError:
        raise HTTPException(status_code=403, detail="无效Token")

# 受保护的API路由
@app.get("/api/data")
async def get_protected_data(token: dict = Depends(validate_temp_token)):
    return {"data": "你的业务数据"}

此方法能有效阻挡直接的curl请求,因为获取Token的前置请求会被浏览器头校验拦截。

组合方案推荐

按优先级组合以下校验,最大化拦截非法请求:

  1. 严格的CORS配置
  2. Origin头校验
  3. Sec-Fetch-*头校验
  4. 短时效临时Token验证

多层校验后,既能保证合法用户的正常访问,又能大幅降低非前端来源请求的通过率。

内容的提问来源于stack exchange,提问作者Jane Wayne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:22:41