Django用户认证怎么实现?

访客 全栈框架 2

本文目录导读:

  1. Django 内置认证系统(最常用)
  2. 使用 Django 内置的 LoginView(更简洁)
  3. 自定义用户模型(扩展字段)
  4. 自定义认证后端(如邮箱登录)
  5. 密码重置(忘记密码)
  6. 最佳实践建议
  7. 完整示例项目结构

Django 提供了强大且安全的用户认证系统,实现起来非常方便,主要分为内置认证(快速实现登录/注册)和自定义认证(扩展字段或登录方式)。

以下是 Django 用户认证的完整实现指南:

Django 内置认证系统(最常用)

Django 自带 django.contrib.auth 应用,默认使用用户名 + 密码认证。

基础配置(通常默认已配置)

检查 settings.pyINSTALLED_APPSMIDDLEWARE

INSTALLED_APPS = [
    # ...
    'django.contrib.auth',      # 认证框架
    'django.contrib.contenttypes', # permission系统依赖
    # ...
]
MIDDLEWARE = [
    # ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # ...
]

执行迁移(创建 auth 相关表):

python manage.py migrate

创建用户(注册)

通常通过 User.objects.create_user() 方法创建(密码会自动加密):

from django.contrib.auth.models import User
from django.shortcuts import render, redirect
def register(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        email = request.POST['email']
        # 创建用户
        user = User.objects.create_user(username=username, 
                                         password=password,
                                         email=email)
        # 可以直接登录(注册后自动登录)
        from django.contrib.auth import login
        login(request, user)
        return redirect('home')
    return render(request, 'register.html')

用户登录

使用 authenticate() 验证,再用 login() 建立会话:

from django.contrib.auth import authenticate, login
def user_login(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)  # 创建用户session
            return redirect('home')
        else:
            # 登录失败
            error_msg = '用户名或密码错误'
            return render(request, 'login.html', {'error': error_msg})
    return render(request, 'login.html')

退出登录

from django.contrib.auth import logout
def user_logout(request):
    logout(request)  # 清除session
    return redirect('login')

在模板中判断用户状态

Django 会在模板中提供 {{ user }} 对象:

<!-- 在模板中 -->
{% if user.is_authenticated %}
    <p>欢迎,{{ user.username }}!</p>
    <a href="{% url 'logout' %}">退出</a>
{% else %}
    <a href="{% url 'login' %}">登录</a>
    <a href="{% url 'register' %}">注册</a>
{% endif %}

视图保护(要求登录才能访问)

from django.contrib.auth.decorators import login_required
@login_required(login_url='/login/')  # 未登录跳转到登录页
def dashboard(request):
    # 只有登录用户能访问
    return render(request, 'dashboard.html')

或者在类视图中:

from django.contrib.auth.mixins import LoginRequiredMixin
class ProfileView(LoginRequiredMixin, View):
    login_url = '/login/'
    # ...

使用 Django 内置的 LoginView(更简洁)

Django 提供了现成的类视图,无需手写表单验证逻辑。

在 urls.py 中直接引用

# urls.py
from django.urls import path
from django.contrib.auth.views import LoginView, LogoutView
from . import views
urlpatterns = [
    path('login/', LoginView.as_view(template_name='login.html'), name='login'),
    path('logout/', LogoutView.as_view(next_page='login'), name='logout'),
    path('register/', views.register, name='register'),
]

创建 login.html 模板

注意:表单字段名必须为 usernamepassword

<!-- login.html -->
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <!-- 或手动写 -->
    <input type="text" name="username" placeholder="用户名">
    <input type="password" name="password" placeholder="密码">
    <button type="submit">登录</button>
</form>
  • 登录成功默认跳转到 settings.LOGIN_REDIRECT_URL(默认 /accounts/profile/),建议在 settings.py 中设置:
    LOGIN_REDIRECT_URL = '/home/'   # 登录后跳转首页
    LOGOUT_REDIRECT_URL = '/login/' # 退出后跳转登录页

自定义用户模型(扩展字段)

如果需要添加手机号、头像等额外字段,推荐使用继承 AbstractUser 的方式。

创建自定义用户模型

# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
    # 继承已有字段(username, password, email...)
    phone = models.CharField(max_length=11, unique=True)
    avatar = models.ImageField(upload_to='avatars/', blank=True)
    bio = models.TextField(blank=True)
    def __str__(self):
        return self.username

修改 settings.py

# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'  # 必须在使用前设置!

创建自定义表单(注册时使用)

# forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ('username', 'email', 'phone', 'password1', 'password2')

注册视图使用新表单

def register(request):
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()  # 直接保存
            login(request, user)
            return redirect('home')
    else:
        form = CustomUserCreationForm()
    return render(request, 'register.html', {'form': form})

自定义认证后端(如邮箱登录)

如果要实现“用邮箱或手机号登录”,需要自定义 authentication backend。

# authentication.py (在app根目录创建)
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth import get_user_model
User = get_user_model()
class EmailBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        # 这里 username 可能是邮箱
        try:
            user = User.objects.get(email=username)  # 按邮箱查找
        except User.DoesNotExist:
            return None
        if user.check_password(password):
            return user
        return None
    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

settings.py 中注册:

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',  # 保留用户名登录
    'myapp.authentication.EmailBackend',          # 新增邮箱登录
]

authenticate(request, username='user@example.com', password='...') 也能登录。


密码重置(忘记密码)

Django 内置了完整的密码重置流程:

# urls.py
from django.contrib.auth import views as auth_views
urlpatterns = [
    # 密码重置:输入邮箱 -> 发送邮件 -> 点击链接 -> 设置新密码
    path('password_reset/', 
         auth_views.PasswordResetView.as_view(template_name='password_reset.html'), 
         name='password_reset'),
    path('password_reset/done/', 
         auth_views.PasswordResetDoneView.as_view(template_name='password_reset_done.html'), 
         name='password_reset_done'),
    path('reset/<uidb64>/<token>/', 
         auth_views.PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html'), 
         name='password_reset_confirm'),
    path('reset/done/', 
         auth_views.PasswordResetCompleteView.as_view(template_name='password_reset_complete.html'), 
         name='password_reset_complete'),
]

settings.py 配置邮箱发送(开发环境可用控制台输出):

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'  # 控制台查看邮件

最佳实践建议

  1. 不要手写密码哈希:使用 create_user()set_password(),Django 会自动加盐哈希。
  2. 使用通用视图:登录/密码重置等直接用 LoginViewPasswordResetView,减少重复代码。
  3. 始终使用 HTTPS:生产环境密码传输必须加密。
  4. 自定义用户模型尽早做:如果项目可能扩展用户字段,在第一次迁移前就设置好 AUTH_USER_MODEL,否则很难修改。

完整示例项目结构

myproject/
├── myapp/
│   ├── models.py          → CustomUser (可选项)
│   ├── forms.py           → 自定义注册表单
│   ├── authentication.py  → 自定义后端 (可选项)
│   ├── views.py           → register, profile, login 等
│   ├── urls.py            → 路由
│   └── templates/
│       └── registration/
│           ├── login.html
│           └── register.html
├── myproject/
│   └── settings.py        → AUTH_USER_MODEL, LOGIN_REDIRECT_URL
└── manage.py

如果你只是需要一个简单的登录/注册页面,用 方案一(内置 auth) 最快;如果需要微信登录、OAuth,可以配合 django-allauth 库,需要我深入某个部分吗?

标签: 认证系统

抱歉,评论功能暂时关闭!