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(内部循环....)

 

 
posted @ 2018-07-08 19:05  yimi+fly  阅读(1377)  评论(1编辑  收藏  举报