一、创建LoginAuth类完成认证过程

使django支持framework

在settings.py中的INSTALLED_APPS字段添加:

"rest_framework"



urls.py

url(r'^login/',views.Login.as_view()),url(r'^books/',views.Books.as_view()),

models.py

fromdjango.dbimportmodels#Createyourmodelshere.classUserInfo(models.Model):name=models.CharField(max_length=32)#写choiceuser_choice=((0,'普通用户'),(1,'会员'),(2,'超级用户'))#指定choice,可以快速的通过数字,取出文字user_type=models.IntegerField(choices=user_choice,default=0)pwd=models.CharField(max_length=32)classUserToken(models.Model):token=models.CharField(max_length=64)user=models.OneToOneField(to=UserInfo)classBook(models.Model):nid=models.AutoField(primary_key=True)name=models.CharField(max_length=32)price=models.DecimalField(max_digits=5,decimal_places=2)publish_date=models.DateField()publish=models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)authors=models.ManyToManyField(to='Author')def__str__(self):returnself.nameclassAuthor(models.Model):nid=models.AutoField(primary_key=True)name=models.CharField(max_length=32)age=models.IntegerField()author_detail=models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)classAuthorDatail(models.Model):nid=models.AutoField(primary_key=True)telephone=models.BigIntegerField()birthday=models.DateField()addr=models.CharField(max_length=64)classPublish(models.Model):nid=models.AutoField(primary_key=True)name=models.CharField(max_length=32)city=models.CharField(max_length=32)email=models.EmailField()def__str__(self):returnself.namedeftest(self):returnself.email

迁移数据库

python3 manage makemigrations
python3 manage migrate


app01/MySerializer.py

fromrest_frameworkimportserializersfromapp01importmodelsclassBookSerializer(serializers.ModelSerializer):classMeta:model=models.Bookfields='__all__'

views.py

fromdjango.shortcutsimportrenderfromdjango.httpimportJsonResponsefromrest_framework.viewsimportAPIViewfromapp01importmodelsimporthashlibimporttimefromdjango.core.exceptionsimportObjectDoesNotExistfromapp01importMySerializer#Createyourviewshere.defget_token(name):#生成一个md5对象md5=hashlib.md5()#往里添加值,必须是bytes格式#time.time()生成时间戳类型,转成字符串,再encode转成bytes格式md5.update(str(time.time()).encode('utf-8'))md5.update(name.encode('utf-8'))returnmd5.hexdigest()classLogin(APIView):authentication_classes=[]defpost(self,request,*args,**kwargs):response={'status':100,'msg':'登录成功'}name=request.data.get('name')pwd=request.data.get('pwd')try:user=models.UserInfo.objects.get(name=name,pwd=pwd)#校验通过,登录成功,生成一个随机字符串(身份标识)tokentoken=get_token(name)#保存到数据库#update_or_create更新或者创建models.UserToken.objects.update_or_create(user=user,defaults={'token':token})response['token']=tokenexceptObjectDoesNotExistase:response['status']=101response['msg']='用户名或密码错误'exceptExceptionase:response['status']=102#response['msg']='未知错误'response['msg']=str(e)returnJsonResponse(response,safe=False)fromrest_frameworkimportexceptionsclassLoginAuth():#函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像defauthenticate(self,request):#从request对像中取出token(也可以从其他地方中取)token=request.query_params.get('token')#去数据库中查询ret=models.UserToken.objects.filter(token=token)ifret:#可以查到,说明认证通过,返回空returnNone#否则会报异常raiseexceptions.APIException('认证失败')fromrest_framework.requestimportRequest#classBooks(APIView):##列表中类型不能加括号#authentication_classes=[LoginAuth,]##defget(self,request,*args,**kwargs):#response={'status':100,'msg':'查询成功'}##必须登录以后,才能获取数据##取出token,取数据库验证,是否登录#token=request.query_params.get('token')#ret=models.UserToken.objects.filter(token=token)#ifret:##认证通过,是登录用户#ret=models.Book.objects.all()#book_ser=MySerializer.BookSerializer(ret,many=True)#response['data']=book_ser.data#else:#response['status']=101#response['msg']='认证不通过'#returnJsonResponse(response,safe=False)#与上面的Books类功能一样,但比上面的那个更加简洁。classBooks(APIView):#列表中类型不能加括号authentication_classes=[LoginAuth,]defget(self,request,*args,**kwargs):response={'status':100,'msg':'查询成功'}ret=models.Book.objects.all()book_ser=MySerializer.BookSerializer(ret,many=True)response['data']=book_ser.datareturnJsonResponse(response,safe=False)

数据库中添加数据测试:

使用Postman测试:

功能:登录后方可查看书的详情信息

使用数据库中的用户名与密码登录服务:

使用token登录来验证查询书的详情信息

若是token验证不成功,就会返回:

二、认证组件的全局使用与局部使用

urls.py、models.py、不变

局部使用:

views.py

fromapp01.MyAuthimportLoginAuthclassBooks(APIView):#列表中类型不能加括号#认证组件局部使用authentication_classes=[LoginAuth,]#认证组件,局部禁用authentication_classes=[]defget(self,request,*args,**kwargs):response={'status':100,'msg':'查询成功'}ret=models.Book.objects.all()book_ser=MySerializer.BookSerializer(ret,many=True)response['data']=book_ser.datareturnJsonResponse(response,safe=False)

app01/MyAuth.py

fromrest_frameworkimportexceptionsfromapp01importmodels#用dnf认证,写一个类classLoginAuth():#函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像defauthenticate(self,request):#从request对像中取出token(也可以从其他地方中取)token=request.query_params.get('token')#去数据库中查询ret=models.UserToken.objects.filter(token=token)ifret:#可以查到,说明认证通过,返回空returnNone#否则会报异常raiseexceptions.APIException('认证失败')

-全局使用
-在setting中配置:

使django支持framework

在settings.py中的INSTALLED_APPS字段添加:

"rest_framework"

REST_FRAMEWORK={'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',],}

-局部禁用,views.py中有:

认证组件,局部禁用authentication_classes=[]


三、权限组建

用户身份不同,权限也不同

urls.py

url(r'^login/',views.Login.as_view()),url(r'^books/',views.Books.as_view()),url(r'^authors/',views.Authors.as_view()),url(r'^users/',views.User.as_view()),

views.py

fromdjango.shortcutsimportrenderfromdjango.httpimportJsonResponsefromrest_framework.viewsimportAPIViewfromapp01importmodelsimporthashlibimporttimefromdjango.core.exceptionsimportObjectDoesNotExistfromapp01importMySerializer#Createyourviewshere.defget_token(name):#生成一个md5对象md5=hashlib.md5()#往里添加值,必须是bytes格式#time.time()生成时间戳类型,转成字符串,再encode转成bytes格式md5.update(str(time.time()).encode('utf-8'))md5.update(name.encode('utf-8'))returnmd5.hexdigest()classLogin(APIView):authentication_classes=[]permission_classes=[]defpost(self,request,*args,**kwargs):response={'status':100,'msg':'登录成功'}name=request.data.get('name')pwd=request.data.get('pwd')try:user=models.UserInfo.objects.get(name=name,pwd=pwd)#校验通过,登录成功,生成一个随机字符串(身份标识)tokentoken=get_token(name)#保存到数据库#update_or_create更新或者创建models.UserToken.objects.update_or_create(user=user,defaults={'token':token})response['token']=tokenexceptObjectDoesNotExistase:response['status']=101response['msg']='用户名或密码错误'exceptExceptionase:response['status']=102#response['msg']='未知错误'response['msg']=str(e)returnJsonResponse(response,safe=False)fromrest_frameworkimportexceptionsfromapp01.MyAuthimportLoginAuthfromrest_framework.requestimportRequestclassBooks(APIView):#列表中类型不能加括号#认证组件局部使用#authentication_classes=[LoginAuth,]#认证组件,局部禁用authentication_classes=[]defget(self,request,*args,**kwargs):response={'status':100,'msg':'查询成功'}ret=models.Book.objects.all()book_ser=MySerializer.BookSerializer(ret,many=True)response['data']=book_ser.datareturnJsonResponse(response,safe=False)#只能超级用户可以查看作者详情,其他人不能看fromapp01.MyAuthimportUserPermissionclassAuthors(APIView):#局部使用#permission_classes=[UserPermission,]#局部禁用#permission_classes=[]defget(self,request,*args,**kwargs):response={'status':100,'msg':'查询成功'}ret=models.Author.objects.all()ser=MySerializer.AuthorSerializer(ret,many=True)response['data']=ser.datareturnJsonResponse(response,safe=False)classUser(APIView):defget(self,request,*args,**kwargs):response={'status':100,'msg':'查询成功'}ret=models.UserInfo.objects.all()ser=MySerializer.UserSer(ret,many=True)response['data']=ser.datareturnJsonResponse(response,safe=False)

settings.py中添加:

#认证组件全局使用REST_FRAMEWORK={'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.LoginAuth',],'DEFAULT_PERMISSION_CLASSES':['app01.MyAuth.UserPermission',],}

app01/MyAuth.py

fromrest_frameworkimportexceptionsfromapp01importmodelsfromrest_framework.authenticationimportBaseAuthentication#用dnf认证,写一个类classLoginAuth(BaseAuthentication):#函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像defauthenticate(self,request):#从request对像中取出token(也可以从其他地方中取)token=request.query_params.get('token')print(token)#去数据库中查询ret=models.UserToken.objects.filter(token=token).first()print(ret)ifret:#可以查到,说明认证通过,返回空returnret.user,ret#否则会报异常raiseexceptions.APIException('认证失败')fromrest_framework.permissionsimportBasePermissionclassUserPermission(BasePermission):#message是出错显示的中文message='没权限查看'defhas_permission(self,request,view):print(request.user)user_type=request.user.user_typeprint(user_type)#取出用户类型对应的文字#固定用法:get_字段名字_display()user_type_name=request.user.get_user_type_display()print(user_type_name)ifuser_type==2:returnTrueelse:returnFalse

app01/MySerializer.py

fromrest_frameworkimportserializersfromapp01importmodelsclassBookSerializer(serializers.ModelSerializer):classMeta:model=models.Bookfields='__all__'classAuthorSerializer(serializers.ModelSerializer):classMeta:model=models.Authorfields='__all__'classUserSer(serializers.ModelSerializer):classMeta:model=models.UserInfofields='__all__'#显示用户类型以中文显示user_type=serializers.CharField(source='get_user_type_display')#上面一句话就ok#user_type=serializers.SerializerMethodField()#defget_user_type(self,obj):#returnobj.get_user_type_display()

models.py

fromdjango.dbimportmodels#Createyourmodelshere.#用户信息classUserInfo(models.Model):name=models.CharField(max_length=32)#写choiceuser_choice=((0,'普通用户'),(1,'会员'),(2,'超级用户'))#指定choice,可以快速的通过数字,取出文字user_type=models.IntegerField(choices=user_choice,default=0)pwd=models.CharField(max_length=32)#用户tokenclassUserToken(models.Model):token=models.CharField(max_length=64)user=models.OneToOneField(to=UserInfo)classBook(models.Model):nid=models.AutoField(primary_key=True)name=models.CharField(max_length=32)price=models.DecimalField(max_digits=5,decimal_places=2)publish_date=models.DateField()publish=models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)authors=models.ManyToManyField(to='Author')def__str__(self):returnself.nameclassAuthor(models.Model):nid=models.AutoField(primary_key=True)name=models.CharField(max_length=32)age=models.IntegerField()author_detail=models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)classAuthorDatail(models.Model):nid=models.AutoField(primary_key=True)telephone=models.BigIntegerField()birthday=models.DateField()addr=models.CharField(max_length=64)classPublish(models.Model):nid=models.AutoField(primary_key=True)name=models.CharField(max_length=32)city=models.CharField(max_length=32)email=models.EmailField()def__str__(self):returnself.namedeftest(self):returnself.email

数据库中添加数据:

使用Postman来登录用户获取token:

使用Postman 中的"s_jun"(只有超级用户有权限查看,其他人没有权限查看)用户的token测试:

其他用户的token查看:



使用postman 查看用户身份类型以及中文方式显示