from flask import Flask, render_template, request, session, redirect, url_for, flash import secrets # For generating secure tokens app = Flask(__name__) app.secret_key = secrets.token_hex(16) # A strong secret key is crucial for sessions # Middleware to generate and validate CSRF tokens @app.before_request def csrf_protect(): if request.method == "POST": token = session.pop('_csrf_token', None) if not token or token != request.form.get('_csrf_token'): flash('CSRF token missing or incorrect.', 'error') return redirect(url_for('login')) # Or render an error page def generate_csrf_token(): if '_csrf_token' not in session: session['_csrf_token'] = secrets.token_hex(16) return session['_csrf_token'] app.jinja_env.globals['csrf_token'] = generate_csrf_token @app.route('/') def index(): return render_template('index.html') @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': # In a real app, validate credentials username = request.form['username'] password = request.form['password'] if username == 'admin' and password == 'password': # DANGER: Never hardcode passwords session['logged_in'] = True flash('Logged in successfully!', 'success') return redirect(url_for('dashboard')) flash('Invalid credentials.', 'error') return render_template('login.html') @app.route('/dashboard') def dashboard(): if not session.get('logged_in'): return redirect(url_for('login')) return render_template('dashboard.html') # Example of a form that requires CSRF protection @app.route('/change_password', methods=['GET', 'POST']) def change_password(): if not session.get('logged_in'): return redirect(url_for('login')) if request.method == 'POST': old_password = request.form['old_password'] new_password = request.form['new_password'] # ... process password change ... flash('Password changed successfully!', 'success') return redirect(url_for('dashboard')) return render_template('change_password.html') if __name__ == '__main__': app.run(debug=True) # Example login.html (simplified, needs CSS) #
# # #
# #
# #
# Example change_password.html (simplified, needs CSS) #
# # #
# #
# #