Django用户认证系统完整实现:内置Auth vs 手动Session对比教程
本文将通过一个完整的Django项目,对比实现两种用户认证系统:Django内置Auth组件和手动Session认证。适合Django初学者理解认证机制差异。
一、项目概述
本项目将创建一个Django项目,实现两种用户认证方式的完整示例:
-
/auth/路径 - 使用Django内置的auth组件 -
/custom/路径 - 使用自定义模型手动实现Session认证
技术对比
|
特性 |
Django内置Auth |
手动Session认证 |
|---|---|---|
|
用户模型 |
内置 |
自定义 |
|
密码存储 |
自动加密 |
明文存储(仅演示) |
|
登录验证 |
|
手动数据库查询 |
|
登录状态 |
|
手动设置Session |
|
访问控制 |
|
自定义装饰器 |
二、环境准备
1. 环境要求
-
Python 3.8+
-
Django 4.0+
-
PyCharm(或其他Python IDE)
2. 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
3. 安装Django
pip install django
三、项目创建和配置
1. 创建Django项目
django-admin startproject django_auth_demo
cd django_auth_demo
2. 创建两个应用
python manage.py startapp auth_demo
python manage.py startapp custom_auth
3. 项目结构
django_auth_demo/
├── manage.py
├── auth_project/ # 项目配置目录
├── auth_demo/ # 内置Auth应用
├── custom_auth/ # 手动Session应用
└── templates/ # 全局模板目录
4. 配置settings.py
修改auth_project/settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'auth_demo',
'custom_auth',
]
# 添加模板目录
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
BASE_DIR / 'templates', # 全局模板目录
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
四、实现Django内置Auth认证系统
1. 配置URL路由
主路由 (auth_project/urls.py):
from django.contrib import admin
from django.urls import path, include
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
urlpatterns = [
path('admin/', admin.site.urls),
path('auth/', include('auth_demo.urls')),
path('custom/', include('custom_auth.urls')),
path('', home, name='home'),
]
应用路由 (auth_demo/urls.py):
from django.urls import path
from . import views
app_name = 'auth_demo'
urlpatterns = [
path('login/', views.auth_login, name='login'),
path('logout/', views.auth_logout, name='logout'),
path('index/', views.auth_index, name='index'),
path('protected/', views.protected_view, name='protected'),
]
2. 编写视图函数 (auth_demo/views.py)
from django.shortcuts import render, redirect
from django.contrib import auth
from django.contrib.auth.decorators import login_required
def auth_login(request):
"""登录视图"""
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(request, username=username, password=password)
if user is not None:
auth.login(request, user)
next_url = request.GET.get('next') or 'auth_demo:index'
return redirect(next_url)
else:
return render(request, 'auth_demo/login.html', {'error': '用户名或密码错误'})
return render(request, 'auth_demo/login.html')
@login_required(login_url='/auth/login/')
def auth_index(request):
"""受保护的首页"""
return render(request, 'auth_demo/index.html', {'user': request.user})
@login_required
def protected_view(request):
"""另一个受保护页面"""
return render(request, 'auth_demo/protected.html')
def auth_logout(request):
"""退出登录"""
auth.logout(request)
return redirect('auth_demo:login')
3. 创建模板文件
登录页面 (auth_demo/templates/auth_demo/login.html):
<!DOCTYPE html>
<html>
<head>
<title>Django Auth登录</title>
<style>
body { font-family: Arial; max-width: 400px; margin: 50px auto; }
.error { color: red; }
input { width: 100%; padding: 8px; margin: 5px 0; }
button { background: #4CAF50; color: white; padding: 10px; border: none; }
</style>
</head>
<body>
<h2>Django内置Auth组件 - 登录</h2>
{% if error %}<p class="error">{{ error }}</p>{% endif %}
<form method="post">
{% csrf_token %}
<input type="text" name="username" placeholder="用户名" required>
<input type="password" name="password" placeholder="密码" required>
<button type="submit">登录</button>
</form>
<p><small>使用超级用户账号登录</small></p>
<p><a href="/custom/register/">前往手动Session注册页面</a></p>
</body>
</html>
首页 (auth_demo/templates/auth_demo/index.html):
<!DOCTYPE html>
<html>
<head>
<title>Auth主页</title>
</head>
<body>
<h2>欢迎回来,{{ user.username }}!</h2>
<p>您已通过Django内置Auth组件成功登录。</p>
<p>用户邮箱:{{ user.email }}</p>
<p>超级用户:{% if user.is_superuser %}是{% else %}否{% endif %}</p>
<ul>
<li><a href="{% url 'auth_demo:protected' %}">访问受保护页面</a></li>
<li><a href="{% url 'auth_demo:logout' %}">退出登录</a></li>
</ul>
<p><a href="/custom/">前往手动Session认证系统</a></p>
</body>
</html>
五、实现手动Session认证系统
1. 定义数据模型 (custom_auth/models.py)
from django.db import models
class UserInfo(models.Model):
"""自定义用户模型(密码明文存储,仅用于演示!)"""
username = models.CharField(max_length=32, unique=True, verbose_name="用户名")
password = models.CharField(max_length=64, verbose_name="密码")
email = models.EmailField(blank=True, verbose_name="邮箱")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
def __str__(self):
return self.username
2. 创建并应用迁移
python manage.py makemigrations custom_auth
python manage.py migrate
3. 配置URL路由 (custom_auth/urls.py)
from django.urls import path
from . import views
app_name = 'custom_auth'
urlpatterns = [
path('', views.index, name='index'),
path('register/', views.register, name='register'),
path('login/', views.login_view, name='login'),
path('logout/', views.logout_view, name='logout'),
path('dashboard/', views.dashboard, name='dashboard'),
path('profile/', views.profile, name='profile'),
]
4. 编写视图函数 (custom_auth/views.py)
from django.shortcuts import render, redirect
from .models import UserInfo
# 自定义登录检查装饰器
def login_required_custom(view_func):
def wrapper(request, *args, **kwargs):
if not request.session.get('is_logged_in'):
return redirect('custom_auth:login')
return view_func(request, *args, **kwargs)
return wrapper
def index(request):
"""主页"""
return render(request, 'custom_auth/index.html')
def register(request):
"""注册视图"""
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
email = request.POST.get('email', '')
if UserInfo.objects.filter(username=username).exists():
return render(request, 'custom_auth/register.html', {
'error': '用户名已存在',
'username': username,
'email': email
})
user = UserInfo.objects.create(
username=username,
password=password, # 注意:实际项目应对密码进行哈希加密!
email=email
)
# 注册成功后自动登录
request.session['is_logged_in'] = True
request.session['user_id'] = user.id
request.session['username'] = user.username
return redirect('custom_auth:dashboard')
return render(request, 'custom_auth/register.html')
def login_view(request):
"""登录视图"""
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
try:
user = UserInfo.objects.get(username=username, password=password)
request.session['is_logged_in'] = True
request.session['user_id'] = user.id
request.session['username'] = user.username
request.session.set_expiry(3600) # 1小时后过期
return redirect('custom_auth:dashboard')
except UserInfo.DoesNotExist:
return render(request, 'custom_auth/login.html', {
'error': '用户名或密码错误',
'username': username
})
return render(request, 'custom_auth/login.html')
@login_required_custom
def dashboard(request):
"""用户仪表板(需要登录)"""
user_id = request.session.get('user_id')
try:
user = UserInfo.objects.get(id=user_id)
except UserInfo.DoesNotExist:
request.session.flush()
return redirect('custom_auth:login')
return render(request, 'custom_auth/dashboard.html', {
'user': user,
'session_info': dict(request.session)
})
@login_required_custom
def profile(request):
"""用户个人资料页(需要登录)"""
user_id = request.session.get('user_id')
try:
user = UserInfo.objects.get(id=user_id)
except UserInfo.DoesNotExist:
request.session.flush()
return redirect('custom_auth:login')
return render(request, 'custom_auth/profile.html', {'user': user})
def logout_view(request):
"""退出登录"""
request.session.flush()
return redirect('custom_auth:index')
5. 创建模板文件
注册页面 (custom_auth/templates/custom_auth/register.html):
<!DOCTYPE html>
<html>
<head>
<title>注册</title>
</head>
<body>
<h2>注册新用户</h2>
{% if error %}<p style="color: red;">{{ error }}</p>{% endif %}
<form method="post">
{% csrf_token %}
<p><input type="text" name="username" value="{{ username|default:'' }}" placeholder="用户名" required></p>
<p><input type="password" name="password" placeholder="密码" required></p>
<p><input type="email" name="email" value="{{ email|default:'' }}" placeholder="邮箱(可选)"></p>
<button type="submit">注册</button>
</form>
<p>已有账户?<a href="{% url 'custom_auth:login' %}">立即登录</a></p>
</body>
</html>
仪表板 (custom_auth/templates/custom_auth/dashboard.html):
<!DOCTYPE html>
<html>
<head>
<title>用户仪表板</title>
</head>
<body>
<h2>欢迎回来,{{ user.username }}!</h2>
<h3>用户信息</h3>
<ul>
<li>用户名: {{ user.username }}</li>
<li>邮箱: {{ user.email|default:"未设置" }}</li>
<li>注册时间: {{ user.created_at }}</li>
</ul>
<h3>Session信息</h3>
<pre>{{ session_info }}</pre>
<h3>导航</h3>
<ul>
<li><a href="{% url 'custom_auth:profile' %}">查看个人资料</a></li>
<li><a href="{% url 'custom_auth:logout' %}">退出登录</a></li>
</ul>
<p><small>这是一个通过手动Session管理登录状态的页面</small></p>
</body>
</html>
六、创建对比首页
在项目根目录创建templates/home.html:
<!DOCTYPE html>
<html>
<head>
<title>Django认证系统演示</title>
<style>
body { font-family: Arial; max-width: 800px; margin: 50px auto; padding: 20px; }
.container { display: flex; justify-content: space-around; margin-top: 30px; }
.system-box { border: 1px solid #ddd; border-radius: 8px; padding: 20px; width: 45%; }
.auth-box { background-color: #f0f8ff; }
.custom-box { background-color: #fff0f5; }
.btn { display: inline-block; padding: 10px 20px; background: #4CAF50; color: white; text-decoration: none; }
</style>
</head>
<body>
<h1>Django用户认证系统演示</h1>
<p>本项目包含两种用户认证实现方式,用于学习和对比:</p>
<div class="container">
<div class="system-box auth-box">
<h2>Django内置Auth组件</h2>
<p>使用Django自带的认证系统</p>
<a href="/auth/login/" class="btn">体验内置Auth系统</a>
</div>
<div class="system-box custom-box">
<h2>手动Session认证</h2>
<p>自定义实现的认证系统</p>
<a href="/custom/" class="btn">体验手动Session系统</a>
</div>
</div>
<div style="margin-top: 40px;">
<h3>技术对比</h3>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<th style="border: 1px solid #ddd; padding: 8px;">特性</th>
<th style="border: 1px solid #ddd; padding: 8px;">Django内置Auth</th>
<th style="border: 1px solid #ddd; padding: 8px;">手动Session</th>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">用户模型</td>
<td style="border: 1px solid #ddd; padding: 8px;">内置User模型</td>
<td style="border: 1px solid #ddd; padding: 8px;">自定义UserInfo模型</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">密码存储</td>
<td style="border: 1px solid #ddd; padding: 8px;">自动加密(安全)</td>
<td style="border: 1px solid #ddd; padding: 8px;">明文存储(演示用)</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">登录验证</td>
<td style="border: 1px solid #ddd; padding: 8px;">authenticate()函数</td>
<td style="border: 1px solid #ddd; padding: 8px;">手动数据库查询</td>
</tr>
</table>
</div>
</body>
</html>
七、运行和测试
1. 创建超级用户
python manage.py createsuperuser
2. 运行开发服务器
python manage.py runserver
3. 访问测试
-
内置Auth系统:http://127.0.0.1:8000/auth/login/
-
手动Session系统:http://127.0.0.1:8000/custom/
4. 测试流程
-
访问首页,选择要测试的系统
-
内置Auth系统:使用
createsuperuser创建的账号登录 -
手动Session系统:先注册新用户,然后登录
-
观察两个系统的差异
八、核心概念总结
1. Django内置Auth组件特点
-
自动化程度高:提供完整的认证流程
-
安全性好:密码自动加密存储
-
集成度高:与Django其他组件无缝集成
-
适合场景:标准Web应用,快速开发
2. 手动Session认证特点
-
控制度高:完全掌控认证流程
-
灵活性强:可自定义所有环节
-
学习价值:帮助理解认证原理
-
适合场景:特殊需求,教学演示
3. 实际项目建议
-
生产环境必须使用Django内置Auth或第三方认证库
-
手动Session实现仅用于学习和理解原理
-
实际项目中应对密码进行哈希加密(使用
make_password和check_password)
九、常见问题解决
1. ModuleNotFoundError: No module named 'xxx'
-
检查应用是否在
settings.py的INSTALLED_APPS中注册 -
检查应用目录是否有
__init__.py文件
2. TemplateDoesNotExist
-
检查模板路径是否正确
-
确认
TEMPLATES配置中的DIRS设置
3. 数据库迁移错误
-
删除数据库文件
db.sqlite3和迁移文件 -
重新运行
python manage.py makemigrations和migrate
十、扩展学习
1. 安全性改进
# 在实际项目中对密码进行哈希加密
from django.contrib.auth.hashers import make_password, check_password
# 存储时加密
hashed_password = make_password('plain_password')
# 验证时比较
check_password('plain_password', hashed_password) # 返回True/False
2. 使用Django内置Auth的自定义用户模型
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
phone = models.CharField(max_length=20)
# 添加自定义字段
3. 第三方认证库
-
Django-allauth:提供社交账号登录
-
Django-rest-framework:REST API认证
-
Django-oauth-toolkit:OAuth2认证
总结
通过本教程,您已经:
-
创建了一个包含两种认证系统的完整Django项目
-
理解了Django内置Auth组件的工作原理
-
掌握了手动Session认证的实现方法
-
学习了两种方式的优缺点和适用场景
这个项目可以帮助您深入理解Django认证机制,为实际项目开发打下坚实基础。建议您根据本文的代码和思路,尝试扩展更多功能,如用户权限管理、密码重置、邮箱验证等。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)