Django认证系统

一、今日学习内容概述

二、用户认证基础实现

2.1 创建自定义用户模型

# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    phone = models.CharField('手机号', max_length=11, blank=True)
    avatar = models.ImageField('头像', upload_to='avatars/', null=True, blank=True)
    bio = models.TextField('个人简介', max_length=500, blank=True)
    
    class Meta:
        verbose_name = '用户'
        verbose_name_plural = verbose_name
        
    def __str__(self):
        return self.username

2.2 配置认证设置

# settings.py
AUTH_USER_MODEL = 'accounts.CustomUser'

# 认证相关设置
LOGIN_URL = '/accounts/login/'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/accounts/login/'

2.3 实现认证视图

# accounts/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = CustomUser
        fields = ('username', 'email', 'phone', 'password1', 'password2')
        
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs['class'] = 'form-control'

# accounts/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import CustomUserCreationForm

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, 'accounts/register.html', {'form': form})

@login_required
def profile(request):
    return render(request, 'accounts/profile.html')

2.4 创建认证模板

<!-- templates/accounts/login.html -->
{% extends 'base.html' %}

{% block content %}
<div class="row justify-content-center">
    <div class="col-md-6">
        <div class="card">
            <div class="card-body">
                <h2 class="card-title text-center">用户登录</h2>
                <form method="post">
                    {% csrf_token %}
                    {{ form.as_p }}
                    <button type="submit" class="btn btn-primary w-100">登录</button>
                </form>
                <p class="text-center mt-3">
                    还没有账号?<a href="{% url 'register' %}">立即注册</a>
                </p>
            </div>
        </div>
    </div>
</div>
{% endblock %}

三、权限系统实现

3.1 创建自定义权限

# app/models.py
class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    
    class Meta:
        permissions = [
            ("can_publish_article", "Can publish article"),
            ("can_edit_others_article", "Can edit others article"),
        ]

3.2 权限装饰器使用

# app/views.py
from django.contrib.auth.decorators import permission_required

@permission_required('app.can_publish_article', raise_exception=True)
def publish_article(request):
    # 发布文章的逻辑
    pass

# 多个权限检查
@permission_required(['app.can_publish_article', 'app.can_edit_others_article'], raise_exception=True)
def edit_article(request):
    # 编辑文章的逻辑
    pass

# 使用用户测试函数
from django.contrib.auth.decorators import user_passes_test

def email_verified(user):
    return user.email and user.is_active

@user_passes_test(email_verified)
def protected_view(request):
    # 受保护的视图逻辑
    pass

3.3 在模板中使用权限

{% if perms.app.can_publish_article %}
    <a href="{% url 'publish_article' %}" class="btn btn-primary">发布文章</a>
{% endif %}

{% if user.has_perm('app.can_edit_others_article') %}
    <a href="{% url 'edit_article' article.id %}" class="btn btn-warning">编辑</a>
{% endif %}

四、用户组管理

4.1 创建和管理用户组

# accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser

class CustomUserAdmin(UserAdmin):
    list_display = ('username', 'email', 'phone', 'is_staff', 'is_active')
    list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
    fieldsets = UserAdmin.fieldsets + (
        ('自定义字段', {'fields': ('phone', 'avatar', 'bio')}),
    )
    
admin.site.register(CustomUser, CustomUserAdmin)

# accounts/views.py
from django.contrib.auth.models import Group
from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.is_superuser)
def manage_groups(request):
    if request.method == 'POST':
        # 创建新用户组
        group_name = request.POST.get('group_name')
        permissions = request.POST.getlist('permissions')
        
        group = Group.objects.create(name=group_name)
        group.permissions.set(permissions)
        
        messages.success(request, f'用户组 {group_name} 创建成功')
        return redirect('manage_groups')
        
    groups = Group.objects.all()
    return render(request, 'accounts/manage_groups.html', {'groups': groups})

五、认证流程图

每天40分玩转Django:Django认证系统-LMLPHP

六、自定义认证后端

6.1 创建自定义认证后端

# accounts/auth_backends.py
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from .models import CustomUser

class EmailOrPhoneBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            # 通过邮箱或手机号查找用户
            user = CustomUser.objects.get(
                Q(username=username) | 
                Q(email=username) |
                Q(phone=username)
            )
            if user.check_password(password):
                return user
            return None
        except CustomUser.DoesNotExist:
            return None

6.2 配置认证后端

# settings.py
AUTHENTICATION_BACKENDS = [
    'accounts.auth_backends.EmailOrPhoneBackend',
    'django.contrib.auth.backends.ModelBackend',
]

七、实用工具函数

# accounts/utils.py
from django.contrib.auth import get_user_model
from django.contrib.auth.tokens import default_token_generator
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode

User = get_user_model()

def send_verification_email(user, request):
    """
    发送邮箱验证邮件
    """
    token = default_token_generator.make_token(user)
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    verification_url = request.build_absolute_uri(
        f'/accounts/verify/{uid}/{token}/'
    )
    
    context = {
        'user': user,
        'verification_url': verification_url,
    }
    
    message = render_to_string('accounts/email/verification.html', context)
    
    send_mail(
        '验证您的邮箱',
        message,
        'noreply@example.com',
        [user.email],
        html_message=message,
    )

def get_user_permissions(user):
    """
    获取用户所有权限(包括组权限)
    """
    if user.is_superuser:
        return User.objects.all().values_list('auth.permission__codename', flat=True)
    
    return user.user_permissions.values_list('codename', flat=True) | \
           user.groups.values_list('permissions__codename', flat=True).distinct()

八、最佳实践建议

  1. 密码安全

    • 使用强密码策略
    • 实现密码过期机制
    • 记录密码修改历史
  2. 会话管理

    • 设置合适的会话超时时间
    • 实现"记住我"功能
    • 多设备登录控制
  3. 权限设计

    • 最小权限原则
    • 合理分组
    • 定期审核权限
  4. 安全防护

    • 实现登录尝试限制
    • 启用CSRF保护
    • 实现双因素认证

九、练习任务

  1. 实现一个完整的用户认证系统,包含:

    • 用户注册(带邮箱验证)
    • 登录(支持用户名/邮箱/手机号)
    • 找回密码
    • 修改个人信息
  2. 创建一个权限管理系统:

    • 自定义权限
    • 用户组管理
    • 权限分配界面
  3. 实现高级功能:

    • OAuth 2.0集成
    • JWT认证
    • API认证

十、总结

今天我们学习了Django认证系统的核心组件:

  1. 用户认证基础知识
  2. 权限系统的实现和使用
  3. 用户组管理
  4. 自定义认证系统

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

12-22 09:05