一、创建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

from django.db import models# Create your models here.class UserInfo(models.Model):    name = models.CharField(max_length=32)    # 写choice    user_choice=((0,'普通用户'),(1,'会员'),(2,'超级用户'))    # 指定choice,可以快速的通过数字,取出文字    user_type=models.IntegerField(choices=user_choice,default=0)    pwd = models.CharField(max_length=32)class UserToken(models.Model):    token = models.CharField(max_length=64)    user = models.OneToOneField(to=UserInfo)class Book(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):        return self.nameclass Author(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)class AuthorDatail(models.Model):    nid = models.AutoField(primary_key=True)    telephone = models.BigIntegerField()    birthday = models.DateField()    addr = models.CharField(max_length=64)class Publish(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):        return self.name    def test(self):        return self.email

迁移数据库

python3 manage makemigrations

python3 manage migrate

app01/MySerializer.py

from rest_framework import serializersfrom app01 import modelsclass BookSerializer(serializers.ModelSerializer):    class Meta:        model = models.Book        fields='__all__'

views.py

from django.shortcuts import renderfrom django.http import JsonResponsefrom rest_framework.views import APIViewfrom app01 import modelsimport hashlibimport timefrom django.core.exceptions import ObjectDoesNotExistfrom app01 import MySerializer# Create your views here.def get_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'))    return md5.hexdigest()class Login(APIView):    authentication_classes = []    def post(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)            # 校验通过,登录成功,生成一个随机字符串(身份标识)token            token = get_token(name)            # 保存到数据库            # update_or_create更新或者创建            models.UserToken.objects.update_or_create(user=user, defaults={'token': token})            response['token'] = token        except ObjectDoesNotExist as e:            response['status'] = 101            response['msg'] = '用户名或密码错误'        except Exception as e:            response['status'] = 102            # response['msg']='未知错误'            response['msg'] = str(e)        return JsonResponse(response, safe=False)from rest_framework import exceptionsclass LoginAuth():    # 函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像    def authenticate(self, request):        # 从request对像中取出token (也可以从其他地方中取)        token = request.query_params.get('token')        # 去数据库中查询        ret = models.UserToken.objects.filter(token=token)        if ret:            # 可以查到,说明认证通过,返回空            return None        #   否则会报异常        raise exceptions.APIException('认证失败')from rest_framework.request import Request# class Books(APIView):#     # 列表中类型不能加括号#     authentication_classes = [LoginAuth, ]##     def get(self, request, *args, **kwargs):#         response = {'status': 100, 'msg': '查询成功'}#         # 必须登录以后,才能获取数据#         # 取出token,取数据库验证,是否登录#         token = request.query_params.get('token')#         ret = models.UserToken.objects.filter(token=token)#         if ret:#             # 认证通过,是登录用户#             ret = models.Book.objects.all()#             book_ser = MySerializer.BookSerializer(ret, many=True)#             response['data'] = book_ser.data#         else:#             response['status'] = 101#             response['msg'] = '认证不通过'#         return JsonResponse(response, safe=False)# 与上面的Books类功能一样,但比上面的那个更加简洁。class Books(APIView):    # 列表中类型不能加括号    authentication_classes = [LoginAuth, ]    def get(self, request, *args, **kwargs):        response = {'status': 100, 'msg': '查询成功'}        ret = models.Book.objects.all()        book_ser = MySerializer.BookSerializer(ret, many=True)        response['data'] = book_ser.data        return JsonResponse(response, safe=False)

数据库中添加数据测试:

图片.png

图片.png

图片.png

使用Postman测试:

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

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

图片.png

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

图片.png

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

图片.png

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

urls.py、models.py、不变

局部使用:

views.py

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

app01/MyAuth.py

from rest_framework import exceptionsfrom app01 import models# 用dnf 认证,写一个类class LoginAuth():    # 函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像    def authenticate(self, request):        # 从request对像中取出token (也可以从其他地方中取)        token = request.query_params.get('token')        # 去数据库中查询        ret = models.UserToken.objects.filter(token=token)        if ret:            # 可以查到,说明认证通过,返回空            return None        #   否则会报异常        raise exceptions.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

from django.shortcuts import renderfrom django.http import JsonResponsefrom rest_framework.views import APIViewfrom app01 import modelsimport hashlibimport timefrom django.core.exceptions import ObjectDoesNotExistfrom app01 import MySerializer# Create your views here.def get_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'))    return md5.hexdigest()class Login(APIView):    authentication_classes = []    permission_classes = []    def post(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)            # 校验通过,登录成功,生成一个随机字符串(身份标识)token            token = get_token(name)            # 保存到数据库            # update_or_create更新或者创建            models.UserToken.objects.update_or_create(user=user, defaults={'token': token})            response['token'] = token        except ObjectDoesNotExist as e:            response['status'] = 101            response['msg'] = '用户名或密码错误'        except Exception as e:            response['status'] = 102            # response['msg']='未知错误'            response['msg'] = str(e)        return JsonResponse(response, safe=False)from rest_framework import exceptionsfrom app01.MyAuth import LoginAuthfrom rest_framework.request import Requestclass Books(APIView):    # 列表中类型不能加括号    # 认证组件局部使用    # authentication_classes = [LoginAuth, ]    # 认证组件,局部禁用 authentication_classes = []    def get(self, request, *args, **kwargs):        response = {'status': 100, 'msg': '查询成功'}        ret = models.Book.objects.all()        book_ser = MySerializer.BookSerializer(ret, many=True)        response['data'] = book_ser.data        return JsonResponse(response, safe=False)# 只能超级用户可以查看作者详情,其他人不能看from app01.MyAuth import UserPermissionclass Authors(APIView):    # 局部使用    # permission_classes = [UserPermission,]    # 局部禁用    # permission_classes = []    def get(self, request, *args, **kwargs):        response = {'status': 100, 'msg': '查询成功'}        ret = models.Author.objects.all()        ser = MySerializer.AuthorSerializer(ret, many=True)        response['data'] = ser.data        return JsonResponse(response, safe=False)class User(APIView):    def get(self, request, *args, **kwargs):        response = {'status': 100, 'msg': '查询成功'}        ret = models.UserInfo.objects.all()        ser = MySerializer.UserSer(ret, many=True)        response['data'] = ser.data        return JsonResponse(response, safe=False)

settings.py中添加:

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

app01/MyAuth.py

from rest_framework import exceptionsfrom app01 import modelsfrom rest_framework.authentication import BaseAuthentication# 用dnf 认证,写一个类class LoginAuth(BaseAuthentication):    # 函数名必须叫这个名字,接收必须两个参数,第二个参数是request对像    def authenticate(self, request):        # 从request对像中取出token (也可以从其他地方中取)        token = request.query_params.get('token')        print(token)        # 去数据库中查询        ret = models.UserToken.objects.filter(token=token).first()        print(ret)        if ret:            # 可以查到,说明认证通过,返回空            return ret.user, ret        #   否则会报异常        raise exceptions.APIException('认证失败')from rest_framework.permissions import BasePermissionclass UserPermission(BasePermission):    # message是出错显示的中文    message = '没权限查看'    def has_permission(self, request,view):        print(request.user)        user_type = request.user.user_type        print(user_type)        # 取出用户类型对应的文字        # 固定用法:get_字段名字_display()        user_type_name = request.user.get_user_type_display()        print(user_type_name)        if user_type == 2:            return True        else:            return False

app01/MySerializer.py

from rest_framework import serializersfrom app01 import modelsclass BookSerializer(serializers.ModelSerializer):    class Meta:        model = models.Book        fields = '__all__'class AuthorSerializer(serializers.ModelSerializer):    class Meta:        model = models.Author        fields = '__all__'class UserSer(serializers.ModelSerializer):    class Meta:        model = models.UserInfo        fields='__all__'    # 显示用户类型以中文显示    user_type=serializers.CharField(source='get_user_type_display')    # 上面一句话就ok    # user_type=serializers.SerializerMethodField()    # def get_user_type(self,obj):    #     return obj.get_user_type_display()

models.py

from django.db import models# Create your models here.# 用户信息class UserInfo(models.Model):    name = models.CharField(max_length=32)    # 写choice    user_choice = ((0, '普通用户'), (1, '会员'), (2, '超级用户'))    # 指定choice,可以快速的通过数字,取出文字    user_type = models.IntegerField(choices=user_choice, default=0)    pwd = models.CharField(max_length=32)# 用户tokenclass UserToken(models.Model):    token = models.CharField(max_length=64)    user = models.OneToOneField(to=UserInfo)class Book(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):        return self.nameclass Author(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)class AuthorDatail(models.Model):    nid = models.AutoField(primary_key=True)    telephone = models.BigIntegerField()    birthday = models.DateField()    addr = models.CharField(max_length=64)class Publish(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):        return self.name    def test(self):        return self.email

数据库中添加数据:

图片.png

图片.png

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

图片.png

图片.png

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

图片.png

其他用户的token查看:

图片.png


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

图片.png