认证和权限的区别:
认证:对用户登录的身份进行校验.
权限:对登录验证通过的用户,能够访问的api和对api能取得的对应级别数据做限制
认证
BasicAuthentication
使用HTTP基本身份验证,根据用户的用户名和密码进行签名。基本身份验证通常只适用于测试。
SessionAuthentication
使用Django的默认会话后端进行身份验证。会话身份验证适用于与网站在同一会话上下文中运行的Ajax客户端。
TokenAuthentication
使用简单的基于令牌HTTP身份验证。令牌身份验证适用于client-server分离的情况,如本机桌面和移动客户端。
使用Django信号机制自动生成Token
导入信号函数、接收信号receiver和Django User模型类
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from rest_framework.authtoken.models import Token
创建用户时生成Token,打开视图类,添加如下代码:
@receiver(post_save, sender=settings.AUTH_USER_MODEL) # Django信号机制
def generate_token(sender, instance=None, created=False, **kwargs):
"""
创建用户时生成Token
:param sender:
:param instance:
:param created: 默认不创建
:param kwargs:
:return:
"""
if created:
Token.objects.create(user=instance)
用户获取Token
打开**项目路由**``urls.py``
导入``from rest_framework.authtoken import views``
添加路由`` path('api-token-auth/', views.obtain_auth_token) # 获取Token的接口``
postman进行验证
单独针对某个接口去设置不同的认证方式
对象级别的认证设置优先于全局
装饰器有顺序,要放在api_view()的下面
导入对应包
from rest_framework.decorators import api_view, authentication_classes
from rest_framework.authentication import BasicAuthentication, SessionAuthentication, TokenAuthentication
对接口设置装饰器
打开postman,用上面生成的Token和用户名、密码测试一下这个接口,Token应该是请求不通的。
对于类视图、通用类视图、视图集的写法是一样的。
class CourseList(APIView):
"""
查询课程
"""
authentication_classes = (BasicAuthentication,)
def get(self, request):
"""
:param request:
:return:
"""
pass
权限
全局设置在上面配置文件已经加过了,下面看下接口权限(对象级别)的权限设置,和认证基本一样。
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated
接口配置登录权限
和认证的一样。
自定义对象权限
from rest_framework import permissions
class IsOwnerOrOnlyRead(permissions.BasePermission):
"""自定义权限:只允许对象的所有者能够编辑"""
def has_object_permission(self, request, view, obj):
"""
所有的request请求都有读权限,因此一律允许GET/HEAD/OPTIONS方法
:param request:
:param view:
:param obj:
:return: bool
"""
if request.method in permissions.SAFE_METHODS: # 点进去可以看到 SAFE_METHODS = ("GET", "HEAD", "OPTIONS")
return True
# 对象的所有者才可以拥有读写权限,比如说是你自己的课程你才能修改
return obj.teacher == request.user
在视图类里添加自定义的权限
可以新建一个用户,用postman测试一下。
使用test用户请求我们添加过权限的路由地址
使用test用户修改、删除课程
具体视图代码如下
class CourseDetail(APIView):
authentication_classes = (BasicAuthentication,)
permission_classes = (IsAuthenticated, IsOwnerOrOnlyRead)
"""
方便共用对象
"""
def get_objects(self, pk):
try:
obj = Course.objects.get(pk=pk)
self.check_object_permissions(self.request, obj)
return obj
except Course.DoesNotExist:
return
"""
查询课程
"""
def get(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_objects(pk=pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
s = CourseSerializer(instance=obj)
return Response(s.data, status=status.HTTP_200_OK)
"""
修改课程
"""
def put(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_objects(pk=pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
s = CourseSerializer(instance=obj, data=request.data)
if s.is_valid():
s.save()
return Response(data=s.data, status=status.HTTP_200_OK)
return Response(data=s.errors, status=status.HTTP_400_BAD_REQUEST)
"""
删除课程
"""
def delete(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_objects(pk=pk)
if not obj:
return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
和视图集写法不同的地方是,获取对象公共方法里需要手动调用check_object_permissions
方法。