三大认证工作原理简介

  认证、权限、频率

源码分析:

  1. from rest_framework.views import APIView

源码分析入口:

内部的三大认证方法封装:

三大组件的原理分析:

权限六表分析

  基于用户权限访问控制的认证(RBAC):Role-Based-Access-Control;基于auth的认证规则(了解)。

Django框架采用的是RBAC认证规则:通常分为:三表规则、五表规则、Django采用的是六表规则。

三表:用户表、角色表、权限表

五表:用户表、角色表、权限表、用户角色关系表、角色权限关系表、用户权限关系表

六表:用户表、角色表、权限表、用户角色关系表、角色权限关系表、用户权限关系表

源码分析三者的关系

用户表:角色groups,权限user_permissions

角色表:用户user_set,权限permissions

权限表:用户user_set,角色group_set

重点:如果自定义User表后,再另一个项目中采用原生User表,完成数据库迁移时,可能失败。

解决的办法:

  (1)、卸载Django,重新安装(源码问题)

  (2)、将django.contrib下面的admin、auth下的数据迁移记录文件全部清空

  1. from django.contrib.auth.models import AbstractUser,User

创建自定义User表

models.py

  1. from django.contrib.auth.models import AbstractUser
  2. class User(AbstractUser):
  3. mobile = models.CharField(max_length=11, unique=True)#设置成唯一的
  4. class Meta:
  5. db_table = 'api_user'
  6. verbose_name = '用户表'
  7. verbose_name_plural = verbose_name
  8.  
  9. def __str__(self):
  10. return self.username

数据库迁移:

  1. >> python3 manage.py makemigrations
  2.  
  3. >> python3 manage.py migrate
  4.  
  5. >> #创建超级用户
  6.  
  7. >>> python3 manage.py createsuperuser
  8.  
  9. >> admin admin123

配置自定义user表

在settings.py下面输入,告诉django系统自己创建自定义的用户表。

  1. AUTH_USER_MODEL = "api/User"

创建好的三表结构

脚本启动测试查询数据

  1. # django脚本话启动
  2. import os, django
  3. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dg_proj.settings")
  4. django.setup()
  5.  
  6. from api import models
  7. user = models.User.objects.first() # type: models.User
  8. print(user.username)
  9. print(user.groups.first().name)
  10. print(user.user_permissions.first().name)
  1. from django.contrib.auth.models import Group
    group = Group.objects.first()
    # print(group.name)
    # print(group.user_set.first().username)
    # print(group.permissions.first().name)
  1.  

认证组件的源码分析

点击进去,逐一分析,第一个分析的是,认证组件,

  1. def perform_authentication(self, request):

需要点击定位到request下面的user方法继续往下查看其内部的封装原理。

内部user的方法:调用了self._authenticare()封装的方法。

点击 self._authenticate查看认证源码的精髓实现认证的部分。

最后分析得出认证类的配置文件

再通过导入模块,查看内部封装认证的原理

  1. from rest_framework.authentication import BaseAuthentication
  2. from rest_framework.authentication import SessionAuthentication

分析BaseAuthentication 和 SessionAuthentication。

自定义认证模块

  新建一个文件夹,来写自定义的认证模块,authentications.py

分析以上源码后,总结该如何书写自定义认证模块的功能

  1. # 自定义认证类
  2. # 1)继承BaseAuthentication类
  3.  
  4. # 2)重新authenticate(self, request)方法,自定义认证规则
  5.  
  6. # 3)认证规则基于的条件:
  7. # 没有认证信息返回None(游客)
  8. # 有认证信息认证失败抛异常(非法用户)
  9. # 有认证信息认证成功返回用户与认证信息元组(合法用户)
  10.  
  11. # 4)完全视图类的全局(settings文件中)或局部(确切的视图类)配置

认证Authentication

 可以在配置文件中配置全局默认的认证方案

  1. REST_FRAMEWORK = {
  2. 'DEFAULT_AUTHENTICATION_CLASSES': (
  3. 'rest_framework.authentication.BasicAuthentication', # 基本认证
  4. 'rest_framework.authentication.SessionAuthentication', # session认证
  5. )
  6. }

  也可以在每个视图views,py中通过设置authencation_classess属性来配置

  1. from rest_framework.authentication import SessionAuthentication, BasicAuthentication
  2. from rest_framework.views import APIView
  3.  
  4. class ExampleView(APIView):
  5. authentication_classes = (SessionAuthentication, BasicAuthentication)
  6. ...

认证失败会有两种可能的返回值:

>>> 401 Unauthorized 未认证

>>> 403 Permission Denied 权限被禁止

书写自定义的认证组件

  api/authentications.py

  1. from rest_framework.authentication import BaseAuthentication
  2. from rest_framework.exceptions import AuthenticationFailed
  3. from . import models
  4. class MyAuthentication(BaseAuthentication):
  5. def authenticate(self, request):
  6. # 前台在请求头携带认证信息,
  7. # 且默认规范用 Authorization 字段携带认证信息,
  8. # 后台固定在请求对象的META字段中 HTTP_AUTHORIZATION 获取
  9. auth = request.META.get('HTTP_AUTHORIZATION', None)
  10.  
  11. # 处理游客
  12. if auth is None:
  13. return None
  14.  
  15. # 设置一下认证字段小规则(两段式):"auth 认证字符串"
  16. auth_list = auth.split()
  17.  
  18. # 校验合法还是非法用户
  19. if not (len(auth_list) == 2 and auth_list[0].lower() == 'auth'):
  20. raise AuthenticationFailed('认证信息有误,非法用户')
  21.  
  22. # 合法的用户还需要从auth_list[1]中解析出来
  23. # 注:假设一种情况,信息为abc.123.xyz,就可以解析出admin用户;实际开发,该逻辑一定是校验用户的正常逻辑
  24. if auth_list[1] != 'abc.123.xyz': # 校验失败
  25. raise AuthenticationFailed('用户校验失败,非法用户')
  26.  
  27. user = models.User.objects.filter(username='admin').first()
  28.  
  29. if not user:
  30. raise AuthenticationFailed('用户数据有误,非法用户')
  31. return (user, None)
  32.  
  33. # 登录:账号密码 => token(账号密码对应的用户)
  34. # 访问需要登录的接口:携带token发送请求 => 校验token,得到用户

views.py

  1. from rest_framework.views import APIView
  2.  
  3. class TestAPIView(APIView):
  4. def get(self, request, *args, **kwargs):
  5. # 如果通过了认证组件,request.user就一定有值
  6. # 游客:AnonymousUser
  7. # 用户:User表中的具体用户对象
  8. print(request.user)
  9. return APIResponse(0, 'test get ok')

postman测试时需要注意的点

  用post请求在Headers的key:Authoriaztion,内携带认证数据返送个后端。

系统权限类

  权限Permissions

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问

  • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断

  • 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断

源码解析

源码分析:

得出权限配置的settings

AllowAny内部封装

内部权限校验的其他方法

  1. """
  2. 1)AllowAny:
  3. 认证规则全部返还True:return True
  4. 游客与登陆用户都有所有权限
  5.  
  6. 2) IsAuthenticated:
  7. 认证规则必须有登陆的合法用户:return bool(request.user and request.user.is_authenticated)
  8. 游客没有任何权限,登陆用户才有权限
  9.  
  10. 3) IsAdminUser:
  11. 认证规则必须是后台管理用户:return bool(request.user and request.user.is_staff)
  12. 游客没有任何权限,登陆用户才有权限
  13.  
  14. 4) IsAuthenticatedOrReadOnly
  15. 认证规则必须是只读请求或是合法用户:
  16. return bool(
  17. request.method in SAFE_METHODS or
  18. request.user and
  19. request.user.is_authenticated
  20. )
  21. 游客只读,合法用户无限制
  22. """

api/views.py 举例校验

  1. from rest_framework.permissions import IsAuthenticated
  2. class TestAuthenticatedAPIView(APIView):
  3. permission_classes = [IsAuthenticated]
  4. def get(self, request, *args, **kwargs):
  5. return APIResponse(0, 'test 登录才能访问的接口 ok')
  6.  
  7. # 因为默认全局配置的权限类是AllowAny
  8. # settings.py
  9. REST_FRAMEWORK = {
  10. # 权限类配置
  11. 'DEFAULT_PERMISSION_CLASSES': [
  12. 'rest_framework.permissions.AllowAny',
  13. ],
  14. }

自定义的权限类

分析:

  1. """
  2. 1) 创建继承BasePermission的权限类
  3. 2) 实现has_permission方法
  4. 3) 实现体根据权限规则 确定有无权限
  5. 4) 进行全局或局部配置
  6.  
  7. 认证规则
  8. i.满足设置的用户条件,代表有权限,返回True
  9. ii.不满足设置的用户条件,代表有权限,返回False
  10. """

utils/permissions.py

  1. from rest_framework.permissions import BasePermission
  2. from django.contrib.auth.models import Group
  3. class MyPermission(BasePermission):
  4. def has_permission(self, request, view):
  5. # 只读接口判断
  6. r1 = request.method in ('GET', 'HEAD', 'OPTIONS')
  7. # group为有权限的分组
  8. group = Group.objects.filter(name='管理员').first()
  9. # groups为当前用户所属的所有分组
  10. groups = request.user.groups.all()
  11. r2 = group and groups
  12. r3 = group in groups
  13. # 读接口大家都有权限,写接口必须为指定分组下的登陆用户
  14. return r1 or (r2 and r3)

views.py

  1. # 游客只读,登录用户只读,只有登录用户属于 管理员 分组,才可以增删改
  2. from utils.permissions import MyPermission
  3. class TestAdminOrReadOnlyAPIView(APIView):
  4. permission_classes = [MyPermission]
  5. # 所有用户都可以访问
  6. def get(self, request, *args, **kwargs):
  7. return APIResponse(0, '自定义读 OK')
  8. # 必须是 自定义“管理员”分组 下的用户
  9. def post(self, request, *args, **kwargs):
  10. return APIResponse(0, '自定义写 OK')

使用权限认证配置

可以在配置文件中设置默认的权限管理类,如:

  1. REST_FRAMEWORK = {
  2. 'DEFAULT_PERMISSION_CLASSES': (
  3. 'rest_framework.permissions.IsAuthenticated',
  4. )
  5. }

如果为指明,则采用如下默认配置

  1. 'DEFAULT_PERMISSION_CLASSES': (
  2. 'rest_framework.permissions.AllowAny',
  3. )

也可以在具体的视图中通过permissions_classes属性来设置,如

  1. from rest_framework.permissions import IsAuthenticated
  2. from rest_framework.views import APIView
  3.  
  4. class ExampleView(APIView):
  5. permission_classes = (IsAuthenticated,)
  6. ...

提供的权限有一下几种

  1. """
  2. - AllowAny 允许所有用户
  3. - IsAuthenticated 仅通过认证的用户
  4. - IsAdminUser 仅管理员用户
  5. - IsAuthenticatedOrReadOnly 已经登陆认证的用户可以对数据进行增删改操作,没有登陆认证的只能查看数据。
  6.  
  7. """

举例

  1. from rest_framework.authentication import SessionAuthentication
  2. from rest_framework.permissions import IsAuthenticated
  3. from rest_framework.generics import RetrieveAPIView
  4.  
  5. class BookDetailView(RetrieveAPIView):
  6. queryset = BookInfo.objects.all()
  7. serializer_class = BookInfoSerializer
  8. authentication_classes = [SessionAuthentication]
  9. permission_classes = [IsAuthenticated]
  1.  

  

drf三大认证:认证组件-权限组件-权限六表-自定义认证组件的使用的更多相关文章

  1. 【Spring Security】六、自定义认证处理的过滤器

    这里接着上一章的自定义过滤器,这里主要的是配置自定义认证处理的过滤器,并加入到FilterChain的过程.在我们自己不在xml做特殊的配置情况下,security默认的做认证处理的过滤器为Usern ...

  2. drf三大组件之认证组件与权限组件

    复习 """ 视图家族 1.视图类:APIView.GenericAPIView APIView:作为drf的基础view:as_view()禁用csrf:dispatc ...

  3. drf认证组件(介绍)、权限组件(介绍)、jwt认证、签发、jwt框架使用

    目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...

  4. DRF认证、自定义认证和权限、自定义权限

    源码分析 """ 1)APIView的dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial( ...

  5. drf三大认证

    源码分析 """ 1)APIView的dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial( ...

  6. 7) 项目准备流程 和 django权限六表

    一.项目准备 1. 创建django项目 2. 创建数据库 —— init文件中声明mysql —— settings中配置数据库 import pymysql pymysql.install_as_ ...

  7. drf token刷新配置、认证组件(使用)、权限组件(使用)、频率组件(使用)、异常组件(使用)

    目录 一.特殊路由映射的请求 二.token刷新机制配置(了解) 三.认证组件项目使用:多方式登录 1.urls.py 路由 2.views.py 视图 3.serializers.py 序列化 4. ...

  8. 8) drf 三大认证 认证 权限 频率

    一.三大认证功能分析 1)APIView的 dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial(request, *ar ...

  9. drf三大组件之频率认证组件

    复习 """ 1.认证组件:校验认证字符串,得到request.user 没有认证字符串,直接放回None,游客 有认证字符串,但认证失败抛异常,非法用户 有认证字符串, ...

随机推荐

  1. Elasticsearch 使用集群 - 创建索引

    章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...

  2. vue学习(十)mixin 偷懒

    一 mixin混入偷懒技术 架子 <div id="app"> {{msg}} </div> <script> let app = new Vu ...

  3. Linux基础命令-02

    Linux基础命令-02:

  4. RPC——看这一篇就…显然不够

    引言 RPC blablabla…… RPC 知识点 扩展 有给老婆解释的如:https://www.jianshu.com/p/2accc2840a1b

  5. cf 609E.Minimum spanning tree for each edge

    最小生成树,lca(树链剖分(太难搞,不会写)) 问存在这条边的最小生成树,2种情况.1.这条边在原始最小生成树上.2.加上这条半形成一个环(加上),那么就找原来这条边2端点间的最大边就好(减去).( ...

  6. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring自动装配Bean

    除了使用 XML 和 Annotation 的方式装配 Bean 以外,还有一种常用的装配方式——自动装配.自动装配就是指 Spring 容器可以自动装配(autowire)相互协作的 Bean 之间 ...

  7. 每天一点点之laravel框架开发 - passport授权报invalid_credentials

    {"error":"invalid_credentials","message":"The user credentials we ...

  8. JZOJ-2019-11-7 A组

    T1 Input 从文件 awesome.in 中读入数据. 第一行 2 个用空格隔开的整数 \(n\), \(P\). 第二行 n 个用空格隔开的整数 \(A_1, \cdots , A_n\). ...

  9. [CQOI2016]K远点对(KD-Tree)

    暴力的做法应该是这样的,维护大小为k的堆,每次插入两点间距离并弹出堆顶. 然后这个做法显然是可以KD-Tree优化的,建立KD-Tree,然后如果该平面内最远点小于堆顶,则直接退出.就当做是复习很久没 ...

  10. vmbox 导入虚拟电脑之后无法上网

    先执行 ip addr 查看有没有分配ip 用root执行dhclient -v命令去通过DHCP协议获取一个ip,在下图的最后一行可以看到ip已经分配成功dhclient命令可以用来释放你的电脑的I ...