YouTip LogoYouTip

Flask Blog Login

In this chapter, you will learn to implement Session user authentication with Flask-Login, which is the most important security guarantee in Flask web development. * * * ## What is Flask-Login? HTTP requests in web applications are essentially stateless β€” the server doesn't automatically remember who you are. Flask-Login implements user state maintenance through the Session mechanism: after login, the server stores the user ID in the Session, and subsequent requests automatically identify the current user. * * * ## Installation and Initialization (venv) $ pip install flask-login ## Example # File path: app.py from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager app = Flask( __name__ ) app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///blog.db' app.config['SECRET_KEY']='your-secret-key-here'# Session encryption key (use environment variable in production) db = SQLAlchemy(app) # Initialize LoginManager login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view='auth.login'# Redirect unlogged-in users to login page login_manager.login_message='Please log in first.' > `SECRET_KEY` is the cornerstone of Flask's security system β€” Session encryption, CSRF tokens, and Flash messages all depend on it. In production, it must be read from environment variables and never hardcoded. * * * ## Defining the User Model Flask-Login requires the User model to implement several methods provided by UserMixin. ## Example # File path: models.py (new) from flask_login import UserMixin from werkzeug.security import generate_password_hash, check_password_hash class User(UserMixin, db.Model): """User model""" __tablename__ ='users' id= db.Column(db.Integer, primary_key=True) username = db.Column(db.String(50), unique=True, nullable=False) email= db.Column(db.String(120), unique=True, nullable=False) password_hash = db.Column(db.String(256), nullable=False) def set_password(self, password): """Hash and encrypt the password (never store plaintext passwords)""" self.password_hash= generate_password_hash(password) def check_password(self, password): """Verify if password matches""" return check_password_hash(self.password_hash, password) def __repr__ (self): return f'' # Define user_loader: Flask-Login uses this function to restore user object from session @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) UserMixin automatically injects the following properties and methods into the User model: | Property/Method | Description | | --- | --- | | is_authenticated | Whether the user is logged in | | is_active | Whether the user is active | | is_anonymous | Whether it's an anonymous user (not logged in) | | get_id() | Get the user primary key ID | Generate and execute the migration: (venv) $ flask db migrate -m "Add User model" (venv) $ flask db upgrade * * * ## Creating Authentication Blueprint ## Example # File path: app/blueprints/auth.py from flask import Blueprint, render_template, redirect, url_for, request, flash from flask_login import login_user, logout_user, login_required, current_user from app.models import User, db auth_bp = Blueprint('auth', __name__) @auth_bp.route("/register", methods=['GET','POST']) def register(): """User registration""" if current_user.is_authenticated: return redirect(url_for('main.index')) if request.method=='POST': username = request.form.get('username','').strip() email= request.form.get('email','').strip() password = request.form.get('password','') # Validate required fields if not username or not email or not password: flash('All fields are required.','error') return render_template('register.html') # Check if username and email already exist if User.query.filter_by(username=username).first(): flash('Username already taken.','error') return render_template('register.html') if User.query.filter_by(email=email).first(): flash('Email already registered.','error') return render_template('register.html') # Create user user= User(username=username,email=email) user.set_password(password)# Encrypt and store password db.session.add(user) db.session.commit() login_user(user)# Auto login after registration flash(f'Registration successful, welcome {username}!','success') return redirect(url_for('main.index')) return render_template('register.html') @auth_bp.route("/login", methods=['GET','POST']) def login(): """User login""" if current_user.is_authenticated: return redirect(url_for('main.index')) if request.method=='POST': username = request.form.get('username','').strip() password = request.form.get('password','') # user_loader finds user from database user= User.query.filter_by(username=username).first() # Verify password (password itself won't be logged) if user is None or not user.check_password(password): flash('Incorrect username or password.','error') return render_template('login.html') login_user(user, remember=request.form.get('remember')) flash(f'Welcome back, {username}!','success') # After login, redirect to the page before login (next parameter in URL) next_page = request.args.get('next') return redirect(next_page or url_for('main.index')) return render_template('login.html') @auth_bp.route("/logout") @login_required # Only logged-in users can logout def logout(): logout_user() flash('Logged out successfully.','info') return redirect(url_for('main.index')) ### Required References in App Design ## Example # File path: app.py - register auth Blueprint from app.blueprints.auth import auth_bp app.register_blueprint(auth_bp) > Never store passwords in plaintext! `generate_password_hash()` uses the PBKDF2 algorithm to perform salted hash on passwords. Even if the database is leaked, attackers cannot reverse-engineer the passwords. Use `check_password_hash()` when verifying passwords. * * * ## Creating Login and Registration Templates ## Example
← Flask Blog Favorites AdminFlask Blog Migrate β†’