Python 核心:Django 鉴权方案全解析
Django 作为 Python 最成熟的 Web 框架,其鉴权系统(Authentication & Authorization)是核心模块之一。它提供了开箱即用的用户认证、权限控制和会话管理,同时高度可扩展。Django 的鉴权方案基于django.contrib.auth模块,遵循“电池内置”原则,但允许自定义扩展。本文从基础到高级,深入解析 Django 4.x+(2026 最新版)的鉴权方案,包括原理、实现、对比和最佳实践。
1. Django 鉴权系统概述
核心概念:
- 认证(Authentication):验证用户身份(谁是你?),如用户名/密码、Token。
- 授权(Authorization):检查用户权限(你能做什么?),如访问特定视图、操作数据。
- 用户模型(User Model):默认
auth.User,可自定义扩展。 - 会话管理:基于 Session 或 Token 维护状态。
工作原理:
- 用户请求到达视图。
- 中间件(如
AuthenticationMiddleware)从请求中提取凭证(Cookie、Header),加载用户对象到request.user。 - 视图中使用装饰器(如
@login_required)检查认证/权限。 - 如果未认证,重定向到登录页或返回 401/403。
默认配置(settings.py):
INSTALLED_APPS=['django.contrib.auth',# 必须启用'django.contrib.contenttypes',# 权限依赖]AUTH_USER_MODEL='auth.User'# 默认用户模型,可自定义如 'myapp.CustomUser'MIDDLEWARE=['django.contrib.sessions.middleware.SessionMiddleware',# 会话支持'django.contrib.auth.middleware.AuthenticationMiddleware',# 认证中间件]AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.ModelBackend']# 默认后端2. 内置认证方案详解
Django 提供了多种开箱即用的鉴权方案,按复杂度分类。
2.1 基于 Session 的用户名/密码认证(默认方案)
原理:用户登录后,Django 生成 Session ID 存入 Cookie,服务器端存储用户状态。
流程:
- 用户提交用户名/密码。
- 调用
authenticate(username, password)验证。 - 如果成功,调用
login(request, user)设置 Session。 - 后续请求携带 Cookie,中间件加载
request.user。
代码示例(views.py):
fromdjango.contrib.authimportauthenticate,login,logoutfromdjango.httpimportJsonResponsedeflogin_view(request):ifrequest.method=='POST':username=request.POST['username']password=request.POST['password']user=authenticate(request,username=username,password=password)ifuserisnotNone:login(request,user)returnJsonResponse({'message':'登录成功'})else:returnJsonResponse({'error':'凭证无效'},status=401)returnJsonResponse({'error':'无效请求'},status=400)deflogout_view(request):logout(request)returnJsonResponse({'message':'登出成功'})- 装饰器使用:
fromdjango.contrib.auth.decoratorsimportlogin_required@login_required# 未登录重定向到登录页defprotected_view(request):returnJsonResponse({'user':request.user.username})- 优点:简单、安全(服务器端存储)。
- 缺点:不适合分布式系统(需共享 Session),移动端不友好。
2.2 基于 Token 的认证(RESTful API 常用)
原理:登录后生成 Token,返回给客户端。后续请求在 Header 中携带 Token(如 Authorization: Token xxx)。
内置支持:Django REST Framework (DRF) 扩展了 Token 认证。
安装 DRF:
pip install djangorestframework配置(settings.py):
INSTALLED_APPS=['rest_framework','rest_framework.authtoken']REST_FRAMEWORK={'DEFAULT_AUTHENTICATION_CLASSES':['rest_framework.authentication.TokenAuthentication','rest_framework.authentication.SessionAuthentication',],}- 代码示例(views.py):
fromrest_framework.authtoken.modelsimportTokenfromrest_framework.decoratorsimportapi_view,authentication_classes,permission_classesfromrest_framework.permissionsimportIsAuthenticatedfromrest_framework.responseimportResponse@api_view(['POST'])defapi_login(request):# ... 验证用户名/密码 ...token,created=Token.objects.get_or_create(user=user)returnResponse({'token':token.key})@api_view(['GET'])@authentication_classes([TokenAuthentication])@permission_classes([IsAuthenticated])defapi_protected(request):returnResponse({'user':request.user.username})客户端使用:Header 中
Authorization: Token <key>优点:无状态、适合 API、分布式系统。
缺点:Token 泄露风险大(需加密传输),无内置过期机制(需自定义)。
2.3 基于 JWT 的认证(高级 Token 方案)
原理:JSON Web Token(JWT)是自包含的 Token,包含用户数据、签名和过期时间。无需服务器存储。
第三方库:推荐
djangorestframework-simplejwt(pip install)配置(settings.py):
REST_FRAMEWORK={'DEFAULT_AUTHENTICATION_CLASSES':['rest_framework_simplejwt.authentication.JWTAuthentication',],}SIMPLE_JWT={'ACCESS_TOKEN_LIFETIME':timedelta(minutes=5),# 访问 Token 有效期'REFRESH_TOKEN_LIFETIME':timedelta(days=1),# 刷新 Token 有效期}- 代码示例:
fromrest_framework_simplejwt.tokensimportRefreshToken@api_view(['POST'])defjwt_login(request):# ... 验证用户名/密码 ...refresh=RefreshToken.for_user(user)returnResponse({'refresh':str(refresh),'access':str(refresh.access_token),})# 使用:Header 中 Authorization: Bearer <access_token>- 优点:无状态、可扩展、支持过期/刷新机制。
- 缺点:Token 较长、无法主动失效(需黑名单)。
3. 权限控制(Authorization)
Django 的权限系统基于用户、组和权限模型。
内置权限:CRUD 操作(如 ‘app.add_model’)。
检查方式:
- 装饰器:
@permission_required('app.change_model') - 代码中:
user.has_perm('app.add_model') - 组:用户可加入组,继承组权限。
- 装饰器:
自定义权限(models.py):
classMeta:permissions=[("can_publish","Can publish posts"),]4. 自定义认证后端
默认后端是用户名/密码,可扩展支持邮箱、第三方登录等。
- 自定义后端(backends.py):
fromdjango.contrib.auth.backendsimportModelBackendfromdjango.contrib.authimportget_user_modelclassEmailBackend(ModelBackend):defauthenticate(self,request,username=None,password=None,**kwargs):UserModel=get_user_model()try:user=UserModel.objects.get(email=username)ifuser.check_password(password):returnuserexceptUserModel.DoesNotExist:returnNone- 配置:
AUTHENTICATION_BACKENDS=['path.to.EmailBackend']5. 鉴权方案对比表
| 方案 | 状态性 | 适用场景 | 安全性 | 复杂度 | 扩展性 |
|---|---|---|---|---|---|
| Session | 有状态 | Web 应用、浏览器端 | 高 | 低 | 中 |
| Token (DRF) | 无状态 | REST API、移动端 | 中 | 中 | 高 |
| JWT | 无状态 | 微服务、分布式系统 | 高 | 高 | 高 |
| OAuth2 | 无状态 | 第三方登录(如 Google) | 高 | 高 | 高 |
6. 最佳实践与注意事项
- 自定义用户模型:项目启动时就定义
AbstractUser子类,避免迁移问题。 - 密码存储:始终用
make_password和check_password,默认 PBKDF2 算法。 - 安全配置:启用 CSRF、HTTPS,设置
SECURE_COOKIE。 - 性能优化:JWT 避免存敏感数据;Session 用 Redis 缓存。
- 第三方集成:用
django-allauth或django-oauth-toolkit支持社交登录/OAuth。 - 常见坑:未启用中间件导致
request.user为 AnonymousUser;自定义模型未设置USERNAME_FIELD。
Django 的鉴权系统强大且灵活,结合 DRF 可轻松构建企业级应用。掌握这些,你就能在 Python Web 开发中游刃有余!
如果想看完整项目代码、OAuth 示例或特定版本差异,随时告诉我!🚀