zoukankan      html  css  js  c++  java
  • 认证组件

    认证简介:

    只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查看,没有登录,就不能查看,这时候需要用到认证组件

     

    需求:写一个简单的登录认证接口:

    先创建好表格:

    class User(models.Model):
        name = models.CharField(max_length=32)
        pwd = models.CharField(max_length=64)
        user_type = models.IntegerField(choices=((1, "超级管理员"), (2, "普通管理员"), (3, "2b用户")), default=3)
    
    # 跟User表做一对一关联
    class Token(models.Model):
        user = models.OneToOneField(to='User')
        token = models.CharField(max_length=64)

    在视图函数中:

    from app01 import models
    from django.core.exceptions import ObjectDoesNotExist  # 异常捕获:对象不存在
    import uuid   # 生成唯一的id
    class Login(APIView):
        def post(self, request):
            response = {'code': 100, 'msg': '登录成功'}
            name = request.data.get('name')
            pwd = request.data.get('pwd')
    
            try:
                # get 有且只有一条才不报错,其他都抛异常
                user = models.User.objects.filter(name=name, pwd=pwd).get()
                # 登录成功,需要去token表中存数据
                # 生成一个唯一的随机字符串: 这用uuid
                token = uuid.uuid4()
                # update_or_create查出来的token,存在就更新,不存在就创建
                models.Token.objects.update_or_create(user=user, defaults={'token': token})
                response['token'] = token
    
            except ObjectDoesNotExist as e:
                response['code'] = 101
                response['msg'] = '用户名或密码错误'
            except Exception as e:        # 捕获所有的异常
                response['code'] = 102
                response['msg'] = str(e)  # 把异常信息返回到前端
    
            return Response(response)

    配置路由:

    url(r'^login/', views.Login.as_view())

    效果演示:

    登录失败展示,用户名错误,然后需要注意的是在访问路由的时候,/login后面一定要加上斜杠,不加会报错

    登录成功(用户名与密码都正确),然后返回了唯一的id:token,在访问获取图书接口的时候需要用它来认证是否登录,登录了才可以访问

    认证组件的使用

     1、在应用名下新建一个py文件写一个认证类,继承BaseAuthentication

    重写authenticate方法,把request对象传入。能从request对象中取出用户携带的token,根据token判断是否登录过,如果登陆过,返回两个值user对象,token对象,如果没有登录就抛异常

    myauth.py中:

    用户登录成功才能够访问所有图书接口,所有首先要获取用户登录的token,然后做校验,如果相同就表示已经登录,就能获取到图书接口

    from app01 import models
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed  # 异常捕获
    
    
    class MyAuth(BaseAuthentication):  # 继承基类BaseAuthentication,重写了authenticate方法,把request对象传入,能从request对象中取出用户携带的token
        def authenticate(self, request):
            # 写认证逻辑
            token = request.GET.get('token')
            token_obj = models.Token.objects.filter(token=token).first()
            if token_obj:
                # 有值表示已经登录
                # token_obj.user 当前登录的user对象,如果这里不返回,视图类里就拿不到request.user.name,就是当前用户对象,所以要返回
                return token_obj.user, token_obj
    
            else:
                # 没有表示没有登录
                raise AuthenticationFailed('没有登录')

    视图函数中:调用了MyAuth类

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app01.myauth import MyAuth
    
    
    # 用户必须登录之后才能访问获取所有图书接口
    class Books(APIView):
        authentication_classes = [MyAuth, ]   # []里可以写多个认证类
    
        def get(self, request):
            # request.user就是当前登录用户,前面必须返回才能获取到
            print(request.user.name)
            return Response('返回了所有的图书')

    路由配置:

    url(r'^books/', views.Books.as_view())

    效果演示:

    如果token校验成功,就登录认证成功,返回了所有图书,如果校验失败,就抛异常:没有登录

    2、局部使用

    在每个类视图类里面写:authentication_classes = [MyAuth,]

    3、全局使用

    在settings里配置,所有的视图类都需要认证,就不需要在视图类写了

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': ['app01.myauth.MyAuth', ]
    }

    4、局部禁用

    但是登录视图类不需要认证,这时候就要用到局部禁用,在视图类里面写上:authentication_classes = []

     

    源码分析:

    APIView里面的dispatch里面的initial里面的perform_authentication

     

    点开perform_authentication去里面看一下

    request是新的request,user是一个方法,被封装成一个数据属性,那这个类我们怎么去找呢?我们需要去Request里面找这个user

    点进去看一下authenticators是什么

    authenticators是Request类实例化的回收传过来的

    然后再找Request是在哪里实例化的  是在封装的时候实例化的,去看一下

    然后点进去看看get_authenticators执行了什么

    那么这个返回装有一个个对象的列表被谁接收了?

    然后这个selr.authenticators又把值返回给了

    通过for循环取出一个个对象,然后对象又调用authenticate方法

    调用的是认证类里面写的autnenticate方法,开始写认证逻辑

    总结

    读源码看到的东西:
        如果在项目的setting.py中配置了REST_FRAMEWORK,默认先从项目的setting中取
        如果取不到,才去默认的drf配置文件中取
        如果用户在视图类中配置了某个,先去用户配置的取
                
    总结:
        先取视图类中配置的 --->>> 项目setting中取 --->>> 默认配置
  • 相关阅读:
    C#继承
    正则表达式
    C#笔记
    斐波那契数
    out参数
    重载和重写
    数组元素交换位置
    Win10图标显示不正常解决办法
    Linux添加sftp用户并限制其访问目录
    pclzip 解压的文件去掉文件夹
  • 原文地址:https://www.cnblogs.com/zhangguosheng1121/p/11129187.html
Copyright © 2011-2022 走看看