diff --git a/.env.example b/.env.example index 217aac8..fbdc3c8 100644 --- a/.env.example +++ b/.env.example @@ -158,3 +158,4 @@ LIB_CSS_CACHE_CONTROL="public, max-age=604800" # Domyślnie: "public, max-age=2592000, immutable" UPLOADS_CACHE_CONTROL="public, max-age=2592000, immutable" +BCRYPT_PEPPER=sekretnyKluczbcrypt \ No newline at end of file diff --git a/app.py b/app.py index 0461f72..bfecce7 100644 --- a/app.py +++ b/app.py @@ -9,6 +9,7 @@ import psutil import hashlib import re import traceback +import bcrypt from pillow_heif import register_heif_opener from datetime import datetime, timedelta, UTC, timezone @@ -49,6 +50,7 @@ from sqlalchemy.orm import joinedload from collections import defaultdict, deque from functools import wraps from flask_talisman import Talisman +from flask_session import Session # OCR import pytesseract @@ -103,9 +105,11 @@ AUTHORIZED_COOKIE_VALUE = app.config.get("AUTHORIZED_COOKIE_VALUE", "80d31cdfe63 AUTH_COOKIE_MAX_AGE = app.config.get("AUTH_COOKIE_MAX_AGE", 86400) HEALTHCHECK_TOKEN = app.config.get("HEALTHCHECK_TOKEN", "alamapsaikota1234") SESSION_TIMEOUT_MINUTES = int(app.config.get("SESSION_TIMEOUT_MINUTES", 10080)) +SESSION_COOKIE_SECURE = app.config.get("SESSION_COOKIE_SECURE") app.config["COMPRESS_ALGORITHM"] = ["zstd", "br", "gzip", "deflate"] app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=SESSION_TIMEOUT_MINUTES) + app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1) DEBUG_MODE = app.config.get("DEBUG_MODE", False) @@ -128,6 +132,13 @@ socketio = SocketIO(app, async_mode="eventlet") login_manager = LoginManager(app) login_manager.login_view = "login" + +# flask-session +app.config["SESSION_TYPE"] = "sqlalchemy" +app.config["SESSION_SQLALCHEMY"] = db # instancja SQLAlchemy +Session(app) + + # flask-compress compress = Compress() compress.init_app(app) @@ -236,10 +247,11 @@ with app.app_context(): admin = User.query.filter_by(is_admin=True).first() username = app.config.get("DEFAULT_ADMIN_USERNAME", "admin") password = app.config.get("DEFAULT_ADMIN_PASSWORD", "admin123") - password_hash = generate_password_hash(password) + #password_hash = generate_password_hash(password) + password_hash = hash_password(password) if admin: - if admin.username != username or not check_password_hash( - admin.password_hash, password + if admin.username != username or not check_password( + admin.password_hash, password ): admin.username = username admin.password_hash = password_hash @@ -293,6 +305,20 @@ def serve_css_lib(filename): app.register_blueprint(static_bp) +def hash_password(password): + pepper = app.config["BCRYPT_PEPPER"] + peppered = (password + pepper).encode("utf-8") + salt = bcrypt.gensalt() + hashed = bcrypt.hashpw(peppered, salt) + return hashed.decode("utf-8") + + +def check_password(stored_hash, password_input): + pepper = app.config["BCRYPT_PEPPER"] + peppered = (password_input + pepper).encode("utf-8") + return bcrypt.checkpw(peppered, stored_hash.encode("utf-8")) + + def allowed_file(filename): return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS @@ -1237,7 +1263,8 @@ def login(): if request.method == "POST": username_input = request.form["username"].lower() user = User.query.filter(func.lower(User.username) == username_input).first() - if user and check_password_hash(user.password_hash, request.form["password"]): + #if user and check_password_hash(user.password_hash, request.form["password"]): + if user and check_password(user.password_hash, request.form["password"]): session.permanent = True login_user(user) # session["logged"] = True @@ -1912,7 +1939,8 @@ def add_user(): flash("Użytkownik o takiej nazwie już istnieje", "warning") return redirect(url_for("list_users")) - hashed_password = generate_password_hash(password) + #hashed_password = generate_password_hash(password) + hashed_password = hash_password(password) new_user = User(username=username, password_hash=hashed_password) db.session.add(new_user) db.session.commit() @@ -1950,7 +1978,8 @@ def reset_password(user_id): flash("Podaj nowe hasło", "danger") return redirect(url_for("list_users")) - user.password_hash = generate_password_hash(new_password) + #user.password_hash = generate_password_hash(new_password) + user.password_hash = hash_password(new_password) db.session.commit() flash(f"Hasło dla użytkownika {user.username} zostało zaktualizowane", "success") return redirect(url_for("list_users")) diff --git a/config.py b/config.py index 8866df9..815ba57 100644 --- a/config.py +++ b/config.py @@ -45,4 +45,7 @@ class Config: CSS_CACHE_CONTROL = os.environ.get("CSS_CACHE_CONTROL", "public, max-age=3600") LIB_JS_CACHE_CONTROL = os.environ.get("LIB_JS_CACHE_CONTROL", "public, max-age=604800") LIB_CSS_CACHE_CONTROL = os.environ.get("LIB_CSS_CACHE_CONTROL", "public, max-age=604800") - UPLOADS_CACHE_CONTROL = os.environ.get("UPLOADS_CACHE_CONTROL", "public, max-age=2592000, immutable") \ No newline at end of file + UPLOADS_CACHE_CONTROL = os.environ.get("UPLOADS_CACHE_CONTROL", "public, max-age=2592000, immutable") + + BCRYPT_PEPPER = os.environ.get("BCRYPT_PEPPER", "sekretnyKluczBcrypt") + diff --git a/requirements.txt b/requirements.txt index 1d18911..84e1cf4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,4 +14,5 @@ opencv-python-headless psycopg2-binary # pgsql pymysql # mysql cryptography # mysql8 -flask-talisman # nagłówki \ No newline at end of file +flask-talisman # nagłówki +bcrypt \ No newline at end of file