zoukankan      html  css  js  c++  java
  • rest_framework-01-认证(用户登录)-内置认证

    rest_framework-01-认证(用户登录)-内置认证

     

    如果我们写API有人能访问,有人不能访问,则需要些认证。

    如何知道该用户是否已登入?

     如果用户登入成功,则给用户一个随机字符串,去访问另一个页面。

    以前写session的时候,都是把session写cookie里面。

    那现在我们可以把随机字符串通过返回值的方式给用户。

    后端通过查看用户的url判断用户有没有token值且这个字符串是否正确也要判断。有则已登入,可以访问;没有则跳回登入页面。

    用户登入

    1.有些api需要用户登入才能访问,有些api不需要用户登入就能访问。

    1.api(app应用) > models.py: 表

    2.创建表数据:用户表

    3.urls.py

    4.views.py:用户登入只有post请求!!!

     

    5.token用md5加密,并保存或更新到数据库中。

    6.post请求,运行结果:

     

    7.token就保存到数据库了。

     

    8.token生成成功后,就将新的token返回给用户。有异常则返回异常。API写完了。

     

     views.py:API写完了。

    运行结果:

     小结:解决: a. 创建两张表 。b. 用户登录(返回token并保存到数据库)。

    认证

    用户所有订单api

    1.订单url

    2.views.py订单视图

     假设这是所有订单数据

    3.运行结果:get请求

    4.如果这个订单只有登入成功的时候才可以看,你会怎么解决???

     

    运行结果:

     rest_framework认证

    5.这段代码假设post请求也要认证,如果再复制一遍就会很冗余。django已经帮我们封装好了,不用自己写。

    6.自定义一个认证类,自己写认证规则。

    7.认证源码:

    8.自己定义认证规则,认证失败则返回一个异常。

     

    9.注意:必须再写一个方法,否则还会报错。

    引入该模块, 加上该方法:先为空。

    查看该模块源码:

     加上该方法:先为空。

    注释一下代码:

    运行结果:

     用户信息api

    1.假设用户信息api也要认证,(登入后才能访问),怎么办呢?

    自定义的一个认证写完了之后,api视图加上就好了。

    2.如果有成千上万个api都需要认证怎么办呢???  接下来全局认证。(不需要每一个视图都自己加上以上代码)全局配置settings.py。

      认证源码流程图:

     源码配置:

    1.dispatch

     2.封装Request

     

    3.for循环认证列表

     

    4.默认去全局的配置文件读

     

    5.如果自己请求函数里面设置了,就用自己的。没设置就用配置文件的。

     

    6.将认证写在配置文件中,不用局部的。

    源码:

    api_settings表示去配置文件中读。

     读 REST_FRAMEWORK 这个key

    7.setting.py  

    8.将认证相关的东西都写在一个文件中。再引入该文件。

     

    settings.py

    REST_FRAMEWORK = {
        # 全局使用的认证类
        "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FrstAuthtication','api.utils.auth.Authtication'],
    }

    views.py:视图文件中只有视图相关的类。

    9.列表里填你自己写的认证类的路径。   view.py里的所有类都不用加了,默认用session全局的认证。

     

    10.登入不需要认证信息。全局认证,个别不需要认证。

    空列表就行

     

    11.运行结果:

    订单接口:

    登入接口:

    订单接口:

    request封装完了(认证配置),接下来继续看源码。

    0.request封装

    1.读取全局认证配置

     

    2.进行认证

    3.initial > 实现认证self.perform_authentication(request)

     

    4.user

    5.获取认证对象,进行下一步步的认证

     

    往下走

     

    6.如果是匿名用户,默认叫什么

    setting.py

    views.py

    urls.py

    运行结果:

    7.源码设置默认用户名:

     

    8.设置匿名用户名

    "UNAUTHENTICATED_USER":lambda :"匿名用户"
    匿名函数没有参数,直接返回字符串

     

    url请求:

    运行结果:

    9.setting.py:

     内置认证

    1.django内置的认证在哪呢?引入BaseAuthentication

    from rest_framework.authentication import BaseAuthentication

     

    BaseAuthentication源码:

    1.

    2.BaseAuthentication 下有两个方法。

    3.推荐继承BaseAuthentication。更规范。

     

    代码:

    from rest_framework import exceptions
    from api import models
    from rest_framework.authentication import BaseAuthentication
    
    # 用户认证
    class FrstAuthtication(BaseAuthentication):
        def authenticate(self,request):
            pass
        def authenticate_header(self, request):
            pass
    
    class Authtication(BaseAuthentication):
        def authenticate(self,request):
            token = request._request.GET.get('token')
            token_obj = models.UserToken.objects.filter(token=token).first()
            if not token_obj:   #  未登入或者是错误的token
                raise exceptions.AuthenticationFailed('用户认证失败!')
            # 认证成功。在rest_framework内部会将整个两个字段赋值给request,以供后续操作使用。
            return (token_obj.user,token_obj)
    
        def authenticate_header(self, request):
            pass
    auth.py 认证文件

    接下来继续走源码:  BasicAuthentication  基于留言器认证

    1.往下走,复制源码

    2.设置请求头的返回值为api

     

    settings.py

    运行结果:

     

    3.views.py: 引入BasicAuthentication

    4.运行结果:

     

    5.看源码

     

    6.改源码,先注释一下2行代码

     

    不注释表示允许用户为匿名用户。

    7.运行结果:浏览器会对用户名和密码加密放到url上,然后发给服务端,进行验证。

    8.还原代码:

     BasicAuthentication原理:

     

    小结:

    今日内容:
        1. 认证
            a. 问题1:有些API需要用户登录成功之后,才能访问;有些无需登录就能访问。
            b. 基本使用认证组件
                解决:
                    a. 创建两张表
                    b. 用户登录(返回token并保存到数据库)
            c. 认证流程原理
                - 见图示
            
            d. 再看一遍源码
                1. 局部视图使用&全局使用
                2. 匿名是request.user = None
                
            e. 内置认证类
                1. 认证类,必须继承:from rest_framework.authentication import BaseAuthentication
                2. 其他认证类:BasicAuthentication
                
            梳理:
                1. 使用 
                    - 创建类:继承BaseAuthentication; 实现:authenticate方法
                    - 返回值:3种返回值
                        - None,我不管了,下一认证来执行。
                        - raise exceptions.AuthenticationFailed('用户认证失败') # from rest_framework import exceptions
                        - (元素1,元素2)  # 元素1赋值给request.user; 元素2赋值给request.auth 
                        
                    - 局部使用
                        from rest_framework.authentication import BaseAuthentication,BasicAuthentication
                        class UserInfoView(APIView):
                            """
                            订单相关业务
                            """
                            authentication_classes = [BasicAuthentication,]
                            def get(self,request,*args,**kwargs):
                                print(request.user)
                                return HttpResponse('用户信息')
                    - 全局使用:
                        REST_FRAMEWORK = {
                            # 全局使用的认证类
                            "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ],
                            # "UNAUTHENTICATED_USER":lambda :"匿名用户"
                            "UNAUTHENTICATED_USER":None, # 匿名,request.user = None
                            "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
                        }
                2. 源码流程
                    - dispatch
                        - 封装request
                            - 获取定义的认证类(全局/局部),通过列表生成时创建对象。
                        - initial
                            - perform_authentication
                                request.user(内部循环....)
     
  • 相关阅读:
    关于uoloadify不能显示效果原因(thinkphp5仿百度糯米)
    thinkphp3.2.3中$this->assign
    PDO
    类的声明 只能有属性和方法(属性没有括号,方法有括号)
    怎删改查
    JS鼠标事件大全
    建表以及 增。删。改。查
    建表、添加数据及数据查询
    html框架
    表的求和及计算
  • 原文地址:https://www.cnblogs.com/yimiflh/p/9280940.html
Copyright © 2011-2022 走看看