如何保护 Flask API 的安全性?
保护 Flask API 的安全性至关重要,以防止未经授权的访问、数据泄露和恶意攻击。以下是加强 Flask API 安全性的最佳实践:
1. 使用身份验证和授权
确保 API 只能被授权用户访问:
(1) 使用 JWT (JSON Web Token)
JWT 是常见的身份验证机制,可用于身份验证和用户权限控制。
安装 Flask-JWT-Extended:
pip install Flask-JWT-Extended
配置 JWT:
from flask import Flask, jsonify, request
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity, JWTManager
app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'super-secret-key'
jwt = JWTManager(app)
@app.route('/login', methods=['POST'])
def login():
username = request.json.get("username")
password = request.json.get("password")
if username == "admin" and password == "password":
token = create_access_token(identity=username)
return jsonify(access_token=token)
return jsonify({"msg": "Invalid credentials"}), 401
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user)
if __name__ == "__main__":
app.run()
示例请求:
curl -X POST http://127.0.0.1:5000/login -H "Content-Type: application/json" -d '{"username":"admin","password":"password"}'
(2) 使用 OAuth 2.0
OAuth 2.0 允许第三方应用程序访问 API,推荐使用如 Auth0、Okta 等服务。
使用 Flask-OAuthlib:
pip install Flask-OAuthlib
(3) API 密钥
为每个客户端分配唯一的 API 密钥,并在请求头中验证。
from flask import request, abort
API_KEYS = {"valid_key_123": "user1"}
@app.before_request
def check_api_key():
api_key = request.headers.get("X-API-Key")
if api_key not in API_KEYS:
abort(401, "Invalid API Key")
2. 使用 HTTPS 保护数据传输
启用 HTTPS 以加密客户端和服务器之间的通信,防止流量嗅探。
-
在生产环境中,使用 Let’s Encrypt 免费 SSL 证书:
sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d yourdomain.com
-
在 Flask 开发环境中使用自签名证书:
app.run(ssl_context=('cert.pem', 'key.pem'))
3. 防止 SQL 注入
使用 ORM(SQLAlchemy) 或参数化查询来防止 SQL 注入。
from sqlalchemy.sql import text
def get_user(user_id):
result = db.session.execute(text("SELECT * FROM users WHERE id=:id"), {"id": user_id})
return result.fetchall()
避免:
# 易受 SQL 注入攻击
cursor.execute("SELECT * FROM users WHERE id = " + user_id)
4. 启用 CSRF 保护
使用 CSRF 令牌防止跨站请求伪造攻击。
安装 Flask-WTF:
pip install Flask-WTF
在 Flask 中启用 CSRF 保护:
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)
app.config['WTF_CSRF_SECRET_KEY'] = 'a-random-secret-key'
5. 速率限制(防止暴力攻击)
使用 Flask-Limiter
限制 API 请求频率,防止暴力攻击。
安装 Flask-Limiter:
pip install Flask-Limiter
配置限流:
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(get_remote_address, app=app, default_limits=["100 per hour"])
@app.route("/login")
@limiter.limit("5 per minute")
def login():
return "This is a rate-limited endpoint"
6. 安全的错误处理
避免暴露敏感的错误信息,统一错误响应。
@app.errorhandler(500)
def internal_error(error):
return jsonify({"message": "An unexpected error occurred"}), 500
@app.errorhandler(404)
def not_found(error):
return jsonify({"message": "Resource not found"}), 404
7. 禁止调试模式(生产环境)
永远不要在生产环境中启用 debug=True
,否则可能导致代码执行漏洞。
if __name__ == '__main__':
app.run(debug=False)
8. 使用 Content Security Policy (CSP)
设置 HTTP 头防止跨站脚本攻击(XSS):
@app.after_request
def set_security_headers(response):
response.headers["Content-Security-Policy"] = "default-src 'self'"
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
return response
9. 输入验证
验证所有用户输入,防止 XSS、SQL 注入等攻击。
使用 Flask-WTForms 验证表单:
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()])
10. 日志与监控
启用日志记录,跟踪 API 调用与错误:
import logging
logging.basicConfig(filename='app.log', level=logging.INFO)
app.logger.info('API Started')
11. 禁止不必要的 HTTP 方法
仅允许特定方法访问 API,如 GET
、POST
。
@app.route("/data", methods=["GET", "POST"])
def data():
pass
12. 使用安全的依赖
定期使用 pip-audit
或 safety
扫描依赖中的安全漏洞:
pip install safety
safety check
13. 运行 Flask 应用程序的安全环境
-
使用
gunicorn
代替 Flask 内置服务器:gunicorn -w 4 -b 0.0.0.0:8000 app:app
-
使用
Docker
将 Flask 应用容器化:FROM python:3.9 WORKDIR /app COPY . /app RUN pip install -r requirements.txt CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:app"]
14. 自动化测试
编写测试以检测安全漏洞,例如:
def test_login(client):
response = client.post('/login', json={"username": "admin", "password": "wrong"})
assert response.status_code == 401
总结
要确保 Flask API 安全,应采取以下措施:
- 身份验证与授权(JWT、OAuth、API Key)
- 启用 HTTPS
- 防止 SQL 注入
- CSRF/XSS 保护
- 速率限制(防止 DDoS)
- 禁用调试模式
- 使用日志和监控
- 最小权限原则
- 保持依赖最新