Of course! A "Login Handler" is a fundamental component in most web applications. It's responsible for managing the entire authentication process: receiving user credentials, verifying them against a database, creating a session, and handling errors.

I'll provide you with a comprehensive guide, starting with a simple, self-contained example and then moving to a more robust, production-ready version using a popular framework.
The Simplest Possible Login Handler (No Framework)
This example uses Python's built-in http.server and sqlite3. It's great for understanding the core logic without the complexity of a framework.
Key Concepts:
- Password Hashing: Never store passwords in plain text! We'll use
bcryptto securely hash passwords. - Sessions: We'll use a simple dictionary to simulate logged-in users. In a real app, you'd use a secure session library.
- Form Handling: The server will serve an HTML form and then process its
POSTrequest.
Step 1: Install Necessary Libraries
pip install bcrypt
Step 2: The Python Code (login_server.py)
This single file contains the server logic, database setup, and HTML.

import http.server
import socketserver
import sqlite3
import bcrypt
from urllib.parse import parse_qs, urlparse
# --- Database Setup ---
def setup_database():
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# Create a users table if it doesn't exist
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL
)
''')
# Add a default user for testing (hashed password for 'password123')
try:
hashed_pw = bcrypt.hashpw('password123'.encode('utf-8'), bcrypt.gensalt())
cursor.execute("INSERT INTO users (username, password_hash) VALUES (?, ?)", ('admin', hashed_pw))
conn.commit()
except sqlite3.IntegrityError:
# User 'admin' already exists, which is fine
pass
conn.close()
# --- Login Handler Logic ---
class LoginHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
# Serve the login page for GET requests
if self.path == '/':
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
# Simple HTML form
html = """
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Login</h1>
<form action="/login" method="post">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
"""
self.wfile.write(html.encode('utf-8'))
else:
super().do_GET()
def do_POST(self):
if self.path == '/login':
# Read the form data
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
parsed_data = parse_qs(post_data.decode('utf-8'))
username = parsed_data.get('username', [None])[0]
password = parsed_data.get('password', [None])[0]
if not username or not password:
self.send_error(400, "Username and password are required.")
return
# Verify credentials against the database
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute("SELECT password_hash FROM users WHERE username = ?", (username,))
result = cursor.fetchone()
conn.close()
if result and bcrypt.checkpw(password.encode('utf-8'), result[0].encode('utf-8')):
# Successful login!
self.send_response(302) # Redirect
self.send_header('Location', '/welcome')
# In a real app, you would set a secure, HttpOnly cookie here for the session
self.end_headers()
print(f"User '{username}' logged in successfully.")
else:
# Failed login
self.send_response(401)
self.send_header('Content-type', 'text/html')
self.end_headers()
html = f"""
<h1>Login Failed</h1>
<p>Invalid username or password.</p>
<a href="/">Try Again</a>
"""
self.wfile.write(html.encode('utf-8'))
else:
self.send_error(404, "Not Found")
# --- Main Execution ---
if __name__ == "__main__":
setup_database()
PORT = 8000
Handler = LoginHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print(f"Server running at http://localhost:{PORT}")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\nServer stopped.")
httpd.server_close()
Step 3: How to Run It
- Save the code as
login_server.py. - Run it from your terminal:
python login_server.py - Open your web browser and go to
http://localhost:8000. - Try logging in with:
- Username:
admin - Password:
password123
- Username:
- Try with incorrect credentials to see the failure message.
A More Robust & Real-World Example (with Flask)
For any real application, you should use a web framework like Flask or Django. They handle routing, sessions, security, and templating much more cleanly.
This example uses:
- Flask: The web framework.
- Flask-SQLAlchemy: To interact with the database easily.
- Flask-Login: To manage user sessions (logging in, logging out, remembering users).
- Werkzeug: For password hashing (it's a dependency of Flask).
Step 1: Project Setup
# Create a project folder and a virtual environment mkdir flask_login_app cd flask_login_app python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate # Install libraries pip install Flask Flask-SQLAlchemy Flask-Login
Step 2: Project Structure
/flask_login_app
|-- venv/
|-- app.py # Main application file
|-- templates/
| |-- base.html # Base template with navigation
| |-- login.html # Login form
| |-- home.html # Welcome page for logged-in users
| |-- signup.html # User registration form
Step 3: The Code (app.py)
from flask import Flask, render_template, redirect, url_for, flash, request
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash
# --- App and Database Configuration ---
app = Flask(__name__)
# A secret key is needed for session management
app.config['SECRET_KEY'] = 'a-very-secret-key-that-you-should-change'
# Configure the SQLite database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login' # Redirect to login page if user is not authenticated
# --- Database Models ---
# UserMixin provides default implementations for the methods that Flask-Login expects user objects to have.
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True, nullable=False)
password_hash = db.Column(db.String(200), nullable=False)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# --- Routes ---
@app.route('/')
def home():
return render_template('home.html', name=current_user.username if current_user.is_authenticated else "Guest")
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = User.query.filter_by(username=username).first()
# Check if user exists and if the password is correct
if user and user.check_password(password):
login_user(user) # This creates the user session
next_page = request.args.get('next')
# Redirect to the next page if it exists, otherwise go to home
return redirect(next_page) if next_page else redirect(url_for('dashboard'))
else:
flash('Login Unsuccessful. Please check username and password', 'danger')
return render_template('login.html')
@app.route('/signup', methods=['GET', 'POST'])
def signup():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# Check if user already exists
if User.query.filter_by(username=username).first():
flash('Username already exists. Please choose a different one.', 'warning')
return redirect(url_for('signup'))
new_user = User(username=username)
new_user.set_password(password)
db.session.add(new_user)
db.session.commit()
flash('Your account has been created! You are now able to log in.', 'success')
return redirect(url_for('login'))
return render_template('signup.html')
@app.route('/dashboard')
@login_required # This decorator ensures only logged-in users can access this route
def dashboard():
return render_template('dashboard.html', name=current_user.username)
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('home'))
# --- Main Execution ---
if __name__ == "__main__":
with app.app_context():
db.create_all() # Create database tables if they don't exist
app.run(debug=True)
Step 4: The HTML Templates
templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">{% block title %}My App{% endblock %}</title>
<style>
body { font-family: sans-serif; margin: 2em; }
nav { margin-bottom: 2em; }
.flash { padding: 1em; background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
</style>
</head>
<body>
<nav>
<a href="{{ url_for('home') }}">Home</a> |
{% if current_user.is_authenticated %}
<span>Hello, {{ current_user.username }}!</span> |
<a href="{{ url_for('logout') }}">Logout</a>
{% else %}
<a href="{{ url_for('login') }}">Login</a> |
<a href="{{ url_for('signup') }}">Sign Up</a>
{% endif %}
</nav>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<hr>
{% block content %}{% endblock %}
</body>
</html>
templates/login.html

{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<h1>Login</h1>
<form method="post">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username" required><br><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password" required><br><br>
<input type="submit" value="Login">
</form>
{% endblock %}
templates/signup.html
{% extends "base.html" %}
{% block title %}Sign Up{% endblock %}
{% block content %}
<h1>Create an Account</h1>
<form method="post">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username" required><br><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password" required><br><br>
<input type="submit" value="Sign Up">
</form>
{% endblock %}
templates/home.html
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome, {{ name }}!</h1>
<p>This is the home page.</p>
{% endblock %}
templates/dashboard.html
{% extends "base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h1>Dashboard</h1>
<p>Welcome to your private dashboard, {{ name }}!</p>
<p>This page is protected and only visible to logged-in users.</p>
{% endblock %}
Step 5: How to Run the Flask App
- Make sure your virtual environment is active.
- Run the app:
flask run - Open your browser to
http://localhost:5000. - You can now sign up for a new account, log in, and see how you're redirected to the protected dashboard. Logging out will take you back to the home page.
