如何将Flask API设为私有仅允许前端调用(代码内实现)
代码内实现Flask API私有访问的方案
以下几种方案都不需要依赖数据库或外部存储,直接在代码内完成权限控制,可根据你的安全需求选择:
1. 检查请求来源(Origin/Referer 头部)
利用浏览器同源策略特性,前端合法请求会携带Origin或Referer头部,直接在代码里定义允许的前端域名,拦截非信任来源的请求。
from flask import Flask, request, abort app = Flask(__name__) # 代码内直接配置允许的前端域名(包含本地开发环境) ALLOWED_ORIGINS = {"https://your-production-frontend.com", "http://localhost:3000"} @app.before_request def validate_request_source(): # 处理CORS预请求(OPTIONS方法) if request.method == "OPTIONS": response = app.make_default_options_response() # 允许信任的域名跨域 response.headers["Access-Control-Allow-Origin"] = next(iter(ALLOWED_ORIGINS)) response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS" response.headers["Access-Control-Allow-Headers"] = "Content-Type" return response # 验证Origin头部 origin = request.headers.get("Origin") if origin and origin not in ALLOWED_ORIGINS: abort(403, description="Access denied: Invalid origin") # 可选:补充验证Referer头部作为双重校验 referer = request.headers.get("Referer") if referer and not any(referer.startswith(domain) for domain in ALLOWED_ORIGINS): abort(403, description="Access denied: Invalid referer") return None # 示例API路由 @app.route("/api/private-data", methods=["GET"]) def get_private_data(): return {"content": "This data is only for your frontend"} if __name__ == "__main__": app.run()
优缺点:实现简单,无额外依赖;但请求头部可以被伪造,适合对安全性要求中等的内部或非公开场景。
2. 预定义API密钥验证
在代码内固定一个API密钥,前端请求时在请求头中携带该密钥,API端直接校验匹配性。
from flask import Flask, request, abort import os app = Flask(__name__) # 优先从环境变量加载密钥,也可以直接写死在代码中(不推荐硬写,用环境变量更安全) API_SECRET = os.getenv("API_SECRET_KEY", "your-fixed-secret-12345") @app.before_request def validate_api_key(): # 跳过OPTIONS预请求 if request.method == "OPTIONS": return # 从请求头获取密钥 received_key = request.headers.get("X-API-Key") if received_key != API_SECRET: abort(403, description="Access denied: Invalid API key") return None # 受保护的API路由 @app.route("/api/protected", methods=["POST"]) def protected_operation(): return {"status": "success", "data": "Sensitive information"} if __name__ == "__main__": app.run()
前端调用提示:发送请求时在headers中添加X-API-Key: your-fixed-secret-12345。
优缺点:验证逻辑直观,无需复杂流程;但密钥可能因前端代码被反编译而泄露,建议配合HTTPS使用,且仅用于非公开前端场景。
3. JWT令牌验证(代码内签名/校验)
使用JWT实现无状态验证,密钥直接在代码内配置,无需存储用户信息到数据库。前端先通过固定凭据获取令牌,之后所有请求携带令牌即可。
需要先安装依赖:pip install pyjwt
import jwt from datetime import datetime, timedelta from flask import Flask, request, abort, jsonify import os app = Flask(__name__) # 从环境变量加载JWT密钥,或直接定义 JWT_SECRET = os.getenv("JWT_SECRET_KEY", "your-jwt-secret-abc") TOKEN_EXPIRY_MINUTES = 60 # 令牌有效期60分钟 # 前端获取令牌的接口(用代码内固定的凭据校验) @app.route("/api/get-token", methods=["POST"]) def get_token(): # 代码内预定义的前端专属凭据 valid_frontend_creds = {"client_id": "your-frontend-app", "client_secret": "fixed-secret-xyz"} request_data = request.get_json() if not request_data: abort(400, description="Missing request data") # 校验前端提交的凭据 if (request_data.get("client_id") != valid_frontend_creds["client_id"] or request_data.get("client_secret") != valid_frontend_creds["client_secret"]): abort(401, description="Invalid credentials") # 生成JWT令牌 payload = { "sub": "frontend-client", "exp": datetime.utcnow() + timedelta(minutes=TOKEN_EXPIRY_MINUTES) } token = jwt.encode(payload, JWT_SECRET, algorithm="HS256") return jsonify({"access_token": token}) # 全局校验JWT的钩子 @app.before_request def validate_jwt_token(): # 跳过令牌获取接口和OPTIONS请求 if request.path == "/api/get-token" or request.method == "OPTIONS": return auth_header = request.headers.get("Authorization") if not auth_header or not auth_header.startswith("Bearer "): abort(401, description="Missing or invalid Authorization header") token = auth_header.split(" ")[1] try: # 校验令牌有效性 payload = jwt.decode(token, JWT_SECRET, algorithms=["HS256"]) # 验证令牌所属的客户端 if payload.get("sub") != "frontend-client": abort(403, description="Not authorized to access this resource") except jwt.ExpiredSignatureError: abort(401, description="Token has expired") except jwt.InvalidTokenError: abort(401, description="Invalid token") return None # 受保护的API路由 @app.route("/api/secure-data", methods=["GET"]) def get_secure_data(): return {"data": "This is highly protected data"} if __name__ == "__main__": app.run()
前端调用提示:先调用/api/get-token获取令牌,之后每个请求的Authorization头设置为Bearer <获取到的token>。
优缺点:安全性更高,令牌有有效期,泄露风险更低;实现稍复杂,但无需外部存储,完全在代码内完成控制。
内容的提问来源于stack exchange,提问作者Archit
相关产品推荐
相关产品推荐

