赞
踩
title: 深入Django:用户认证与权限控制实战指南
date: 2024/5/7 18:50:33
updated: 2024/5/7 18:50:33
categories:
tags:
在开始使用Django之前,需要确保已经安装了Python环境。在安装好Python后,可以使用以下命令安装Django:
pip install Django
确保已安装Django后,可以使用以下命令检查版本:
django-admin --version
创建一个新的Django项目:
django-admin startproject myproject
进入项目目录:
cd myproject
创建一个新的Django应用:
python manage.py startapp myapp
Django默认提供一个基本的用户模型,如果需要定制用户模型,可以在myproject/settings.py
中进行设置。
例如,可以添加一个新的字段age
:
# myproject/settings.py
AUTH_USER_MODEL = 'myapp.NewUser'
# myapp/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class NewUser(AbstractUser):
age = models.PositiveIntegerField(null=True, blank=True)
def __str__(self):
return f'{self.username} ({self.email})'
在数据库迁移中应用新的用户模型:
python manage.py makemigrations
python manage.py migrate
现在,已经完成了基本的Django项目和应用的创建,并设置了一个基础的用户模型。
在Django中,AUTH_USER_MODEL
设置决定了你如何处理用户。默认的用户模型是django.contrib.auth.models.User
,但如你之前设置的,可以创建自定义用户模型。例如,NewUser
模型需要继承AbstractUser
,并包含username
,email
, 和age
等字段。
UserCreationForm
和UserChangeForm
可以用于用户注册,通常在myapp/forms.py
中定义。在views.py
UserCreationForm.as_view()
创建视图。from django.contrib.auth import get_user_model
from django.urls import reverse_lazy
from django.views import generic
class RegisterView(generic.CreateView):
form_class = get_user_model().forms.UserCreationForm
success_url = reverse_lazy('login')
template_name = 'registration/register.html'
LoginView
和LogoutView
在django.contrib.auth.views
中,使用LoginView.as_view()
和LogoutView.as_view()
。from django.contrib.auth.views import LoginView, LogoutView
class CustomLoginView(LoginView):
template_name = 'registration/login.html'
views.py
中,你可以使用@login_required
装饰器确保只有登录用户才能访问某些视图。from django.contrib.auth.decorators import login_required
@login_required
def protected_view(request):
# 只有已登录用户可以访问的视图
...
要自定义登录或注册视图,可以创建一个类视图并定义get
和post
方法。在urls.py
中,使用path
来映射URL到这些视图。
from django.urls import path
from .views import CustomLoginView, CustomRegisterView
urlpatterns = [
path('login/', CustomLoginView.as_view(), name='login'),
path('register/', CustomRegisterView.as_view(), name='register'),
]
Django的CSRF(跨站请求伪造)保护是通过在表单中添加一个隐藏的CSRF
token来实现的。确保在所有需要用户交互的表单(如注册和登录表单)中使用{% csrf_token %}
模板标签。
此外,你可以在settings.py
中启用CSRF保护:
CSRF_COOKIE_NAME = 'my_custom_cookie_name'
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
这将确保CSRF令牌的安全传输。
认证中间件
AD:首页 | 一个覆盖广泛主题工具的高效在线平台
是Django提供的一种处理请求和响应的机制,它位于视图函数之前和之后。在认证中,django.contrib.auth.middleware.AuthenticationMiddleware
负责检测请求是否已通过身份验证。如果用户未登录,中间件会重定向到登录页面。一旦用户登录,中间件会设置request.user
,使得视图可以访问用户信息。
Django的认证系统会在用户登录后自动设置request.user
,这使得在视图中可以通过request.user
访问用户信息。但如果你想在会话之外存储用户状态(例如,记住用户名),可以使用
AD:专业搜索引擎
django.contrib.auth.middleware.SessionAuthenticationMiddleware
,它会将用户信息存储在会话中。如果需要自定义登录状态的持久性,可以考虑使用django.contrib.auth.backends.RemoteUserBackend
或创建自己的Backend
实现。
认证信号是Django的一种通知机制,用于在认证过程中触发特定事件。例如,user_logged_in
和user_logged_out
信号分别在用户登录和登出时发送。你可以通过注册接收器来处理这些信号,执行额外的操作,如发送邮件通知或更新用户会话记录。
from django.contrib.auth import get_user_model
from django.dispatch import receiver
from django.db.models.signals import post_save
# 注册接收器
@receiver(post_save, sender=get_user_model())
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
# 用户创建时,创建用户profile
else:
# 用户更新时,更新userprofile
通过这种方式,你可以扩展Django认证系统的功能,而无需直接修改核心代码。
Django的权限系统主要依赖于django.contrib.auth.models
模块中的以下几个模型:
User
:表示用户,每个用户都有一个唯一的用户名和密码。Group
:用于组织用户,一个用户可以属于多个组。Permission
:表示一个操作或资源的权限,例如“管理博客”或“查看文章”。UserPermission
(也称为user_has_perm
):关联用户和权限,表示用户拥有特定的权限。在Django中,用户和权限通常是通过Group
来关联的。用户可以被添加到一个或多个组中,而组则被赋予了特定的权限。这样,如果一个用户属于某个具有特定权限的组,那么该用户就自动获得了该组的所有权限。通过这种方式,可以实现角色(如管理员、编辑员等)的权限管理。
Group
模型,你可以创建新的组,然后将用户添加到组中。例如:group = Group.objects.create(name='Administrators')
user = User.objects.get(username='john')
group.user_set.add(user)
Permission
模型,为组赋予特定的权限,然后将组与这些权限关联起来。例如:permission = Permission.objects.get(codename='add_article')
group.permissions.add(permission)
user.has_perm()
或user.has_module_perms()
方法检查用户是否具有特定的权限。if request.user.has_perm('blog.add_article'):
# 用户有添加文章的权限
通过这种方式,Django的权限系统允许你以灵活的方式管理用户对应用的不同部分的访问。
Django提供了一个名为@permission_required
的装饰器,用于在视图函数中检查用户是否具有特定权限。例如:
from django.contrib.auth.decorators import permission_required
def some_view(request):
@permission_required('blog.add_article')
def inner_view(request):
# 视图代码,如果用户没有添加文章的权限,将被重定向到登录页面
...
return inner_view(request)
如果用户没有blog.add_article
权限,请求会重定向到登录页面,或者根据设置显示一个403 Forbidden错误。
Django允许你自定义权限类来实现更复杂的权限检查。创建一个继承自BasePermission
的类,然后在has_permission
方法中定义你的逻辑:
from django.contrib.auth.models import Permission
from django.contrib.auth.base_permissions import BasePermission
class IsSuperAdmin(BasePermission):
def has_permission(self, request, view):
# 检查用户是否是超级管理员
return request.user.is_superuser
然后在视图中使用这个自定义权限:
def some_view(request):
permission_classes = (IsSuperAdmin,)
# 使用自定义权限检查
if not request.user.has_perm(IsSuperAdmin()):
return HttpResponseForbidden('You are not authorized.')
...
@permission_required
装饰器是快速添加权限检查的好工具,但也要注意不要过度使用,可能导致代码难以理解和维护。AD:漫画首页
遵循这些最佳实践,可以确保你的权限系统既安全又易于管理。
django-guardian是一个Django应用,用于在Django项目中实现更细粒度的权限控制。django-guardian允许你将权限授予单个对象,而不仅仅是对整个模型的访问权限。
django-guardian为你提供了一种在Django中实现更细粒度的权限控制的方法。django-guardian的核心是ObjectPermission
模型,用于将权限与单个对象关联。
django-guardian允许你:
首先,安装django-guardian:
pip install django-guardian
在你的Django项目中,添加'guardian'
到INSTALLED_APPS
中,并在MIDDLEWARE
中添加'guardian.middleware.UpdatePermissionsMiddleware'
。
接下来,让我们创建一个简单的应用,并在其中使用django-guardian:
创建一个名为articles
的应用:
python manage.py startapp articles
在articles
应用中,创建一个名为models.py
的文件,并添加以下代码:
from django.db import models
from django.contrib.auth.models import User
from guardian.shortcuts import assign_perm, get_objects_for_user
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
在articles
应用中,创建一个名为views.py
的文件,并添加以下代码:
from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.http import HttpResponseForbidden from articles.models import Article, assign_perm, get_objects_for_user @login_required def article_list(request): user = request.user articles = get_objects_for_user(user, 'articles.view_article', klass=Article) return render(request, 'articles/article_list.html', {'articles': articles}) @login_required def assign_article_permissions(request, article_id): user = request.user article = get_object_or_404(Article, id=article_id) if request.method == 'POST': if user.has_perm('articles.change_article', article): assign_perm('articles.view_article', user, article) return HttpResponse('Assigned view permission.') else: return HttpResponseForbidden('You do not have the permission to change article.') return render(request, 'articles/assign_permissions.html', {'article': article})
在articles
应用中,创建一个名为templates/articles
的文件夹,并在其中创建一个名为assign_permissions.html
的文件:
<form method="post">
{% csrf_token %}
<input type="submit" value="Assign Permission">
</form>
在articles
应用中,创建一个名为urls.py
的文件,并添加以下代码:
from django.urls import path
from . import views
urlpatterns = [
path('', views.article_list, name='article_list'),
path('assign_permissions/<int:article_id>/', views.assign_article_permissions, name='assign_permissions'),
]
在你的项目中,将articles
应用的urls.py
添加到主urls.py
中:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('articles/', include('articles.urls')),
]
现在,你可以运行你的项目,并在文章列表中查看权限管理的实例。在这个例子中,我们使用django-guardian为每个用户分配了对文章的特定视图权限。
你可以使用django-guardian的assign_perm
和get_objects_for_user
函数来分配和检查权限。在这个例子中,我们使用了一个名为view_article
的权限,可以在admin.py
中进行定义:
from django.contrib import admin
from django.contrib.auth.models import Permission
from articles.models import Article
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'author')
def save_model(self, request, obj, form, change):
if not obj.pk:
assign_perm('articles.view_article', request.user, obj)
obj.save()
admin.site.register(Article, ArticleAdmin)
这样,当你在Django管理界面中创建一个新文章时,将自动为当前用户分配view_article
权限。
django-guardian为你提供了一种更细粒度的权限控制方法,可以在Django项目中实现更强大的权限管理。
在Django中,视图是处理HTTP请求的函数或类。为了在视图中检查用户的权限,可以使用django-guardian
提供的has_perm
和get_objects_for_user
函数。以下是一个基本的视图检查权限的例子:
from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from guardian.shortcuts import has_perm @login_required def some_view(request): user = request.user article = Article.objects.get(pk=1) # 假设你有一个名为Article的模型 # 检查用户是否有查看文章的权限 if not has_perm('articles.view_article', article, user): return HttpResponseForbidden("You don't have permission to view this article.") # 如果用户有权限,继续执行 # ... return render(request, 'some_template.html', {'article': article})
在这个例子中,has_perm
函数检查用户是否有指定的权限(在这个例子中是articles.view_article
)对给定的对象(article
)。
在模板中,你可能想要显示用户是否具有特定的权限。Django模板语言允许你使用条件语句来检查这些权限。以下是一个简单的例子:
{% if user.has_perm('articles.view_article', article) %}
<p>You have permission to view this article.</p>
{% else %}
<p>You do not have permission to view this article.</p>
{% endif %}
在这个模板片段中,如果用户具有articles.view_article
权限,has_perm
表达式会返回True
,否则返回False
,从而决定显示不同的内容。
你也可以在模板中使用get_objects_for_user
来获取用户具有特定权限的对象,并根据这些对象的内容进行渲染:
{% if object_list %}
<ul>
{% for object in object_list %}
{% if user.has_perm('articles.view', object) %}
<li>{{ object.title }} (You can view)</li>
{% else %}
<li>{{ object.title }} (You cannot view)</li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No objects found.</p>
{% endif %}
这样,模板会根据用户的权限动态地显示内容,提供一个用户友好的界面。
Django REST
framework提供了多种认证方式,包括基本认证(BasicAuthentication)、令牌认证(TokenAuthentication)和会话认证(SessionAuthentication)等。可以在项目的设置文件中进行配置。以下是一个基本的认证配置示例:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
)
}
在这个配置中,REST framework将使用基本认证和会话认证来处理API请求。
API权限控制是确保API的安全性和保护数据的重要部分。Django REST
framework提供了多种权限控制策略,包括只读权限(ReadOnly)、对象级权限(ObjectPermissions)和自定义权限类(CustomPermission)等。可以在视图中配置权限控制策略。以下是一个使用对象级权限的视图示例:
from rest_framework import viewsets, permissions
from myapp.models import Article
from myapp.serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [permissions.DjangoModelPermissions]
在这个视图中,我们使用了DjangoModelPermissions,这意味着用户只能访问他们拥有的对象。如果用户试图访问他们不拥有的对象,REST
framework将返回一个403 Forbidden响应。
如果你需要更细粒度的权限控制,可以使用自定义权限类。以下是一个简单的自定义权限类示例:
from rest_framework import permissions
class CustomPermission(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.user.is_staff:
return True
return False
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [CustomPermission]
在这个示例中,我们创建了一个名为CustomPermission的自定义权限类,它只允许管理员用户访问API。如果用户不是管理员,则返回一个403
Forbidden响应。
总之,Django REST framework为RESTful API的认证和权限控制提供了多种方式和工具,可以根据项目需求进行选择和定制。
在Web应用程序中,用户会话管理是非常重要的,它涉及到用户登录、注销和会话状态的管理。Django提供了内置的会话管理功能,而Django
REST framework也提供了相应的支持。通过使用SessionAuthentication认证类,Django REST framework可以与Django的会话管理系统集成,从而实现用户会话管理。
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
)
}
通过将SessionAuthentication添加到DEFAULT_AUTHENTICATION_CLASSES中,可以启用基于会话的认证,从而实现用户会话管理。
客户端认证是指在API请求中对客户端进行身份验证的过程。Django REST framework支持多种客户端认证方式,包括OAuth2和JWT(JSON Web
Token)等。这些认证方式可以通过第三方库来实现,比如djangorestframework-simplejwt
用于JWT认证。
以下是一个简单的JWT认证配置示例:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
通过将JWTAuthentication添加到DEFAULT_AUTHENTICATION_CLASSES中,可以启用JWT认证,从而实现客户端认证。
多因素认证是指在用户登录或进行敏感操作时,除了用户名和密码外,还需要提供第二种或多种身份验证因素的过程。Django REST
framework本身并没有内置的多因素认证功能,但可以通过结合第三方库来实现。例如,可以使用django-mfa
等库来实现多因素认证功能。
通过使用这些第三方库,可以实现诸如短信验证码、一次性密码(OTP)等多因素认证方式,从而提高系统的安全性。
综上所述,Django REST framework提供了丰富的支持,可以轻松实现用户会话管理、客户端认证和多因素认证等高级主题。开发人员可以根据项目需求选择合适的认证方式,并结合相关的第三方库来实现所需的功能。
建立一个简单的博客系统是一个很好的实战项目,可以涵盖认证与权限控制等方面。下面是一个基本的Django REST
framework博客系统的示例,其中包括了认证与权限控制的应用。
首先,我们需要创建一个Django应用,并定义博客文章的模型、序列化器、视图和URL配置。
# models.py from django.db import models class Post(models.Model): title = models.CharField(max_length=100) content = models.TextField() author = models.ForeignKey('auth.User', on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) # serializers.py from rest_framework import serializers from .models import Post class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ['id', 'title', 'content', 'author', 'created_at'] # views.py from rest_framework import viewsets from .models import Post from .serializers import PostSerializer class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all() serializer_class = PostSerializer # urls.py from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import PostViewSet router = DefaultRouter() router.register(r'posts', PostViewSet) urlpatterns = [ path('', include(router.urls)), ]
接下来,我们将添加认证与权限控制。
# settings.py INSTALLED_APPS = [ # ... 'rest_framework', 'blog', # assuming 'blog' is the name of the app ] REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ], }
在上述代码中,我们将默认权限设置为IsAuthenticated,这意味着只有经过身份验证的用户才能访问API。我们还配置了SessionAuthentication和TokenAuthentication作为默认的认证类,这样用户可以使用会话验证或令牌验证进行身份验证。
最后,我们需要为用户创建博客文章的权限。我们可以使用Django的自定义权限类来实现这一点。
# permissions.py
from rest_framework import permissions
class IsAuthorOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.author == request.user
然后,将这个权限类应用到我们的视图中。
# views.py
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from .permissions import IsAuthorOrReadOnly
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsAuthorOrReadOnly]
现在,我们已经完成了一个简单的博客系统,并应用了认证与权限控制。用户需要经过身份验证才能访问API,并且只有文章的作者才有权限对文章进行修改或删除。
你可以在Django官方文档中找到最新的Django文档,包括教程、API参考和发布说明等。
这些工具和库都是Django社区广泛使用和推荐的,可以帮助你更高效地开发和管理Django应用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。