v2.1: Security - Captcha, Admin-Login, Auth-Decorator
This commit is contained in:
+50
@@ -0,0 +1,50 @@
|
||||
import os
|
||||
import hashlib
|
||||
import random
|
||||
import time
|
||||
from functools import wraps
|
||||
from flask import session, request, jsonify
|
||||
|
||||
# Config
|
||||
ADMIN_PASSWORD_HASH = os.environ.get('ADMIN_PASSWORD', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi')
|
||||
SECRET_KEY = os.environ.get('SESSION_SECRET', 'dev-secret-change-in-production')
|
||||
|
||||
def generate_captcha():
|
||||
a = random.randint(1, 15)
|
||||
b = random.randint(1, 15)
|
||||
op = random.choice(['+', '-'])
|
||||
if op == '+':
|
||||
answer = a + b
|
||||
else:
|
||||
answer = a - b
|
||||
token = hashlib.sha256(f"{a}{op}{b}{int(time.time()/600)}captcha".encode()).hexdigest()[:16]
|
||||
return {
|
||||
"question": f"{a} {op} {b} = ?",
|
||||
"token": token,
|
||||
"answer": answer
|
||||
}
|
||||
|
||||
def verify_captcha(token, answer):
|
||||
if not token or not answer:
|
||||
return False
|
||||
stored = session.get('captcha_answer')
|
||||
if stored and str(stored) == str(answer):
|
||||
session.pop('captcha_answer', None)
|
||||
return True
|
||||
return False
|
||||
|
||||
def require_auth(role='admin'):
|
||||
def decorator(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
if 'user_role' not in session:
|
||||
return jsonify({"error": "Unauthorized"}), 401
|
||||
if role == 'admin' and session['user_role'] != 'admin':
|
||||
return jsonify({"error": "Admin required"}), 403
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
return decorator
|
||||
|
||||
def check_admin_password(password):
|
||||
from werkzeug.security import check_password_hash
|
||||
return check_password_hash(ADMIN_PASSWORD_HASH, password)
|
||||
Reference in New Issue
Block a user