Help me een aangepaste middleware te implementeren voor het afhandelen van CORS in mijn Flask-toepassing
description
Door deze prompt te gebruiken, kunnen gebruikers de veiligheid van hun Flask-toepassingen verbeteren terwijl ze noodzakelijke cross-origin verzoeken toestaan, wat de functionaliteit en gebruikerservaring verbetert.
prompt
try_prompt
Ik wil een aangepaste middleware in mijn Flask-toepassing implementeren om Cross-Origin Resource Sharing (CORS) efficiënt te beheren. Mijn huidige structuur is: {{app_structuur}}. Leg uit hoe ik middleware kan mak ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Om een aangepaste middleware voor CORS in jouw Flask-toepassing te implementeren, kun je een before_request- of after_request-handler toevoegen die de juiste headers toevoegt. Hier is een overzicht van de aanpak en best practices:
1. Middleware maken voor CORS-afhandeling:
- Gebruik een functie die wordt aangeroepen na elke request (bijvoorbeeld met `after_request`) om CORS-headers toe te voegen.
- Controleer of de request een preflight (OPTIONS) verzoek is en handel dat correct af.
2. Toegestane origins configureren:
- Definieer een lijst of set met toegestane origins.
- Bij elk verzoek controleer je of de 'Origin'-header overeenkomt met een van de toegestane origins.
- Voeg alleen de 'Access-Control-Allow-Origin' header toe als de origin toegestaan is.
3. Preflight-verzoeken beheren:
- Detecteer of het verzoek een OPTIONS-verzoek is.
- Voeg de nodige headers toe zoals 'Access-Control-Allow-Methods' en 'Access-Control-Allow-Headers'.
- Geef een 200 OK reactie terug zonder verdere verwerking.
4. Beste praktijken voor veiligheid:
- Beperk de toegestane origins strikt; vermijd het toestaan van '*', tenzij je geen restricties hebt.
- Specificeer expliciet welke headers en methods toegestaan zijn.
- Overweeg het gebruik van bestaande bibliotheken zoals Flask-CORS voor eenvoud en betrouwbaarheid, tenzij je volledige controle wilt.
voorbeeld van implementatie:
```python
from flask import Flask, request, make_response
app = Flask(__name__)
# Geconfigureerde lijst met toegestane origins
TOEGESTANE_ORIGINS = {'https://voorbeeld.nl', 'https://anderedomein.com'}
@app.after_request
def cors_middleware(response):
origin = request.headers.get('Origin')
if origin in TOEGESTANE_ORIGINS:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Vary'] = 'Origin'
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS, PUT, DELETE'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
return response
@app.before_request
def handle_options():
if request.method == 'OPTIONS':
response = make_response()
origin = request.headers.get('Origin')
if origin in TOEGESTANE_ORIGINS:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Vary'] = 'Origin'
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS, PUT, DELETE'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
return response
# Je blueprints en routes volgen hier
if __name__ == '__main__':
app.run()
```
Samenvatting:
- Gebruik `after_request` om headers toe te voegen.
- Detecteer en handel preflight (OPTIONS) verzoeken af.
- Beperk toegestane origins voor maximale veiligheid.
- Vermijd het gebruik van '*' tenzij echt nodig.
- Overweeg het gebruik van Flask-CORS voor eenvoud en betrouwbaarheid.
Zo zorg je voor een veilige en efficiënte CORS-afhandeling in jouw Flask-applicatie met meerdere blueprints.
provider: deepseek
model: deepseek-chat
Zeker! Ik zal je stap voor stap uitleggen hoe je een aangepaste CORS-middleware kunt implementeren in je Flask-applicatie met blueprints.
## Basis CORS Middleware Implementatie
```python
from flask import Flask, request, jsonify
from functools import wraps
def cors_middleware(app):
@app.before_request
def handle_cors():
"""CORS middleware voor alle verzoeken"""
# Configuratie van toegestane origins
allowed_origins = [
'https://jouwdomein.nl',
'https://api.jouwdomein.nl',
'http://localhost:3000',
'http://127.0.0.1:3000'
]
# Controleer of de origin is toegestaan
origin = request.headers.get('Origin')
if origin in allowed_origins:
# Stel CORS headers in voor toegestane origin
response_headers = {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Max-Age': '86400' # 24 uur cache
}
# Voeg headers toe aan response
for key, value in response_headers.items():
from flask import g
if not hasattr(g, 'cors_headers'):
g.cors_headers = {}
g.cors_headers[key] = value
@app.after_request
def add_cors_headers(response):
"""Voeg CORS headers toe aan response"""
if hasattr(request, 'g') and hasattr(request.g, 'cors_headers'):
for key, value in request.g.cors_headers.items():
response.headers[key] = value
return response
@app.before_request
def handle_preflight():
"""Behandel preflight OPTIONS verzoeken"""
if request.method == 'OPTIONS':
response = jsonify({'status': 'preflight'})
add_cors_headers(response)
return response, 200
```
## Gebruik in je Flask App
```python
from flask import Flask
app = Flask(__name__)
# Registreer de middleware
cors_middleware(app)
# Voorbeeld blueprint
from flask import Blueprint
api_bp = Blueprint('api', __name__)
@api_bp.route('/data', methods=['GET', 'POST', 'OPTIONS'])
def handle_data():
if request.method == 'GET':
return jsonify({'data': 'voorbeeld data'})
elif request.method == 'POST':
return jsonify({'status': 'success'}), 201
app.register_blueprint(api_bp, url_prefix='/api')
```
## Geavanceerde CORS Middleware met Configuratie
```python
import os
from flask import g
class CORSMiddleware:
def __init__(self, app=None):
self.app = app
if app:
self.init_app(app)
def init_app(self, app):
self.allowed_origins = app.config.get('CORS_ALLOWED_ORIGINS', [])
self.allowed_methods = app.config.get('CORS_ALLOWED_METHODS',
['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'])
self.allowed_headers = app.config.get('CORS_ALLOWED_HEADERS',
['Content-Type', 'Authorization'])
@app.before_request
def cors_before_request():
self._set_cors_headers()
@app.after_request
def cors_after_request(response):
return self._add_cors_headers(response)
def _set_cors_headers(self):
origin = request.headers.get('Origin')
if origin in self.allowed_origins:
g.cors_origin = origin
# Preflight verzoek afhandelen
if request.method == 'OPTIONS':
response = jsonify({'status': 'preflight'})
self._add_cors_headers(response)
return response, 200
def _add_cors_headers(self, response):
if hasattr(g, 'cors_origin'):
response.headers['Access-Control-Allow-Origin'] = g.cors_origin
response.headers['Access-Control-Allow-Methods'] = ', '.join(self.allowed_methods)
response.headers['Access-Control-Allow-Headers'] = ', '.join(self.allowed_headers)
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Max-Age'] = '86400'
return response
# Configuratie in Flask app
app.config['CORS_ALLOWED_ORIGINS'] = [
'https://veiligedomein.nl',
'https://api.veiligedomein.nl'
]
```
## Beste Praktijken voor Veiligheid
### 1. Strict Origin Beleid
```python
# ✅ GOED: Specifieke domeinen
allowed_origins = [
'https://jouwproductie-domein.nl',
'https://api.jouwproductie-domein.nl'
]
# ❌ SLECHT: Wildcard voor alles
# 'Access-Control-Allow-Origin': '*'
```
### 2. Environment-based Configuratie
```python
import os
def get_allowed_origins():
env = os.getenv('FLASK_ENV', 'production')
if env == 'development':
return ['http://localhost:3000', 'http://127.0.0.1:3000']
elif env == 'staging':
return ['https://staging.jouwdomein.nl']
else: # production
return ['https://jouwdomein.nl', 'https://www.jouwdomein.nl']
```
### 3. Beveiligingsheaders
```python
def add_security_headers(response):
"""Voeg aanvullende beveiligingsheaders toe"""
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'DENY'
response.headers['X-XSS-Protection'] = '1; mode=block'
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
return response
app.after_request(add_security_headers)
```
### 4. Rate Limiting voor CORS Endpoints
```python
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@api_bp.route('/sensitive-data', methods=['GET'])
@limiter.limit("10 per minute")
def sensitive_data():
return jsonify({'data': 'gevoelige data'})
```
### 5. Validatie en Sanitizatie
```python
import re
def validate_origin(origin):
"""Valideer origin format"""
if not origin:
return False
# Controleer op geldig URL format
pattern = r'^https?://([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(:\d+)?$'
return bool(re.match(pattern, origin))
def sanitize_headers(headers):
"""Sanitize request headers"""
allowed = ['content-type', 'authorization', 'x-requested-with']
return [h for h in headers if h.lower() in allowed]
```
## Complete Implementatie Voorbeeld
```python
from flask import Flask, request, g, jsonify
import os
import re
app = Flask(__name__)
class SecureCORSMiddleware:
def __init__(self, app):
self.app = app
self.init_app(app)
def init_app(self, app):
self.allowed_origins = self._load_allowed_origins()
@app.before_request
def handle_cors():
self._process_cors()
@app.after_request
def add_headers(response):
return self._add_cors_headers(response)
def _load_allowed_origins(self):
env = os.getenv('FLASK_ENV', 'production')
if env == 'development':
return ['http://localhost:3000', 'http://127.0.0.1:3000']
else:
# Haal origins uit environment variabelen voor veiligheid
origins = os.getenv('CORS_ALLOWED_ORIGINS', '').split(',')
return [origin.strip() for origin in origins if origin.strip()]
def _process_cors(self):
origin = request.headers.get('Origin')
if origin and self._is_valid_origin(origin):
g.cors_allowed = True
g.cors_origin = origin
if request.method == 'OPTIONS':
return jsonify({'status': 'preflight'}), 200
def _is_valid_origin(self, origin):
if origin not in self.allowed_origins:
return False
# Extra validatie
pattern = r'^https?://([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(:\d+)?$'
return bool(re.match(pattern, origin))
def _add_cors_headers(self, response):
if hasattr(g, 'cors_allowed') and g.cors_allowed:
response.headers.update({
'Access-Control-Allow-Origin': g.cors_origin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Max-Age': '3600'
})
return response
# Initialiseer middleware
SecureCORSMiddleware(app)
if __name__ == '__main__':
app.run(debug=True)
```
## Belangrijkste Veiligheidsmaatregelen:
1. **Geen wildcard origins** in productie
2. **Environment-specifieke configuratie**
3. **Strikte origin validatie**
4. **Beperk toegestane methodes** tot wat nodig is
5. **Implementeer rate limiting** voor gevoelige endpoints
6. **Gebruik HTTPS** in productie
7. **Houd dependencies up-to-date**
Deze implementatie biedt een goede balans tussen functionaliteit en veiligheid voor je Flask-applicatie met blueprints.

