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
接下来继续走源码: 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(内部循环....)