目录
一、认证组件
简介:
-
登录认证的限制
-
认证组件是drf框架给我们提供的认证接口,它能够在请求进入视图函数/类前进验证(例如:认证用户是否登录),对不符合认证的请求进行拦截并返回校验失败的信息
(1)、登录接口
# 认证是基于登录的接口上面操作的 所以前戏编写一个简单的登录接口
models.py
class User(models.Model): # 简易的用户信息账号密码
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
def __str__(self):
return self.username
'跟User表是一对一外键关联,存储用户登录状态用的 [这个表可以没有,如果没有,把字段直接写在User表上也可以]'
class UserToken(models.Model): # 用户信息登录记录表
user = models.OneToOneField(to='User', on_delete=models.CASCADE) # 一对一关联
token = models.CharField(max_length=32, null=True) # 如果用户没有登录则没有值 如果登录则有值
views.py
'登录接口功能:自动生成路由+登录功能,不用序列化,因此继承ViewSet即可'
class UserView(ViewSet):
@action(methods=['POST'], detail=False, url_path='login', url_name='login')
def login(self, request):
username = request.data.get('username') # 获取用户名与密码
password = request.data.get('password')
user = User.objects.filter(username=username, password=password).first() # 比对用户名与密码
if user:
token = str(uuid.uuid4())
# uuid4 随机获得永不重复的字符串 机制跟Cookie中的验证码一样
# 在userToken表中存储一下:1 从来没有登录过,插入一条, 2 登录过,修改记录
UserToken.objects.update_or_create(defaults={'token': token}, user=user)
# 通过user去UserToken表中查数据,如果能查到,使用defaults的数据更新,如果查不到,直接通过user和defaults的数据新增
# kwargs 传入的东西查找,能找到,使用defaults的更新,否则新增一条
return Response({'code': 100, 'msg': '登录成功', 'token': token})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
urls.py
from rest_framework.routers import SimpleRouter, DefaultRouter
router = SimpleRouter()
router.register('users', views.UserView, 'users')
urlpatterns += router.urls
'''这个时候一个简单的登录接口就写好了 每次登录都会更新Token 相当于登录了之前的设备就无效了 '''
update_or_create
源码如下:
def update_or_create(self, defaults=None, **kwargs):
defaults = defaults or {}
self._for_write = True
with transaction.atomic(using=self.db):
try:
obj = self.select_for_update().get(**kwargs)
except self.model.DoesNotExist:
params = self._extract_model_params(defaults, **kwargs)
obj, created = self._create_object_from_params(kwargs, params, lock=True)
if created:
return obj, created
for k, v in defaults.items():
setattr(obj, k, v() if callable(v) else v)
obj.save(using=self.db)
return obj, False
(2)、认证组件使用步骤
1.需要写一个认证类,因此我们需要在应用中另外创建一个py文件编写认证类,需要继承
BaseAuthentication
这个类
- 通过查看源码我们可以发现有个
authenticate
方法需要我们重写,否则就会报错,这就是我们需要编写认证功能的类
class BaseAuthentication:
def authenticate(self, request):
raise NotImplementedError(".authenticate() must be overridden.")
def authenticate_header(self, request):
pass
2.重写
authenticate
方法,在该方法在中实现登录认证
-
token
在哪带的?如何认证它是登录了的? -
用
token
来判断是否登陆,登陆了在访问的时候带上token
,目前阶段我们直接在地址栏中携带token
的数据,后面可以在请求头中添加token
的数据
3、如果认证成功,返回两个值【返回
None
或两个值(固定的:当前登录用户,token)】
4、认证不通过,用
AuthenticationFailed
类抛异常
代码如下:
authenticate.py(认证类)
# 自己写的认证类,继承某个类
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserToken
class LoginAuth(BaseAuthentication):
def authenticat