登录认证:某个接口必须登录后才能访问。
登录接口原理:登录成功返回随机字符串,携带随机字符串【认证】 通过,再继续访问某个接口
drf提供了很方便的写认证,读APIView源码时,三大认证在视图类的方法之前执行的。
-用户表,用户token表
-前端传入用户名密码----》视图类---》登录方法---》校验用户名密码是否正确,如果正确 生成随机字符串存入数据库---》把随机字符串返回给前端
'''**模型类**''' class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32)class UserToken(models.Model): token = models.CharField(max_length=32) # 用户登录成功签发的随机字符串 user = models.OneToOneField(to='User',on_delete=models.CASCADE) '''**路由**''' from rest_framework.routers import SimpleRouter from .views import UserView,BookView router=SimpleRouter() router.register('user',UserView,'user') urlpatterns = [ ] urlpatterns+=router.urls '''**视图类**''' class UserView(ViewSet): authentication_classes = [] # 局部禁用 # 127.0.0.1:8080/user/user/login--->post @action(methods=['post', ], detail=False) 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: # 登录成功 # 生成一个随机字符串---》uuid--》生成一个随机不重复的值 token = str(uuid.uuid4()) # python 动态强类型 # 存到UserToken表中---》两种情况:之前有了就更新,之前没有就新增 # 有就更新,没有就修改 # defaults=None, **kwargs:传入的去查询,如果能查到使用defaults给的更新 UserToken.objects.update_or_create(user=user, defaults={'token': token}) # UserToken.objects.update_or_create( defaults={'token': token},kwargs={'user':user}) return Response({'code': 100, 'msg': '登录成功', 'token': token}) else: return Response({'code': 101, 'msg': '用户名或密码错误'})
-第一步:写一个类,继承BaseAuthentication
-第二步:在类中重写authenticate方法
-第三步:在方法中做验证,如果通过,返回两个值,如果不通过,抛AuthenticationFailed的异常
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from .models import UserToken class LoginAuth(BaseAuthentication): def authenticate(self, request): # 做验证,验证用户是否登录 # 放到请求地址中/请求头中 token=request.query_params.get('token') # 去数据库查 token在不在 user_token=UserToken.objects.filter(token=token).first() if user_token: # 验证通过了,返回两个值,第一个值是当前登录用户,第二个值是token return user_token.user,token else: # 验证失败 raise AuthenticationFailed('小伙子,您没有登录,不能访问')
-局部使用-->视图类中
class BookView(APIView): authentication_classes = [LoginAuth,]
-全局使用---》配置文件
REST_FRAMEWORK = { # 全局使用认证类 'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',] }
-局部禁用-->视图类中
class BookView(APIView): authentication_classes = []
前端调用接口时
http://127.0.0.1:8000/user/books?token=27954a0e-9b0b-442d-8aff-839ec9f70960
登录成功了,但是有的接口区分权限,有的人有权限,有的人没权限。
用户表新增一个 用户类型字段:超级管理员,普通管理员,普通用户,用于区分用户权限。
-第一步:写一个类,继承BasePermission
-第二步:重写has_permission方法
-第三步:在has_permission中,进行权限的判断,如果有权限,返回True,如果没有权限,返回False,返回的中文提示信息,使用message字段标识
from rest_framework.permissions import BasePermission class PermissionAuth(BasePermission): message='你不是超级用户,不能访问' def has_permission(self, request, view): # 判断权限---》由于权限的执行在认证后执行,到这说明已经认证通过了,认证通过了request.user就是当前登录用户 if request.user.user_type ==1: # 如果有权限,return True return True else: # 用户类型中文 self.message='你是:%s用户,不能访问'%request.user.get_user_type_display() # 如果没有有权限,return False return False
-局部使用-->视图类中
class BookView(APIView): permission_classes = [PermissionAuth,]
-全局使用---》配置文件
REST_FRAMEWORK = { # 全局使用认证类 'DEFAULT_PERMISSION_CLASSES':['app01.auth.PermissionAuth',] }
-局部禁用-->视图类中
class BookView(APIView): permission_classes = []
# python 是动态强类型语言 # go 是静态强类型语言 # java 是静态强类型语言---》隐士类型转换 #js 是动态弱类型语言 # 动态:解释型语言 # 强弱指的是:数据类型强:不同类型之间不允许之间运算 # 弱类型:不同类型之间不需要转换可以之间运算