Django
其实python中,我们用户权限的认证有好几种,先说django中我们自己带的---------->
1.中间件,中间件的意义顾名思义,就是一个处于用户请求进来和返回数据的中间一个组件,我们用户用户登录的时候完全可以设置中间件进行所有的用户登录验证
#用户表 class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) #和Role(角色表)建立多对多的关系 role = models.ManyToManyField('Role') def __str__(self): return self.name #角色表 class Role(models.Model): title = models.CharField(max_length=32) #和Permission(权限表)建立多对多的关系 permission=models.ManyToManyField('Permission') def __str__(self): return self.title class Permission(models.Model): title = models.CharField(max_length=32) #不同的角色的人有不同的访问网址 url = models.CharField(max_length=32) def __str__(self): return self.title
.数据的迁移以及添加表的字段和url
#数据的迁移 #makemigrations #migrate admin.py from django.contrib import admin #把表引过来 #from app01.models import User #from app01.models import Role #from app01.models import Permission admin.site.register(User)admin.site.register(Role)admin.site.register(Permission) #以上三种情况也可以进行插入数据,但是显示出来的是一个个的对象,建议使用下面的代码: admin.site.register(User) class RoleConfig(admin.ModelAdmin): # 按照指定的字段 显示 list_display=["title"] admin.site.register(Role,RoleConfig) #自定义的类,让它按照我想要的字段进行展示,啥名字都可以,但是一定要记得继承ModelAdmin这个类 class PermissionConfig(admin.ModelAdmin): list_display=["pk","title","url"] ordering = ["pk"] admin.site.register(Permission,PermissionConfig)
创建超级用户登录后台进行添加url权限
urlpatterns = [ path('admin/', admin.site.urls), path('login/',views.login), path('orders/', views.order), path('orders/add/', views.addorder), re_path('orders/edit/(d+)/', views.editorder), re_path('orders/delete/(d+)/', views.deleteorder), path('customers/', views.customers), path('customers/add/', views.addcustomers), re_path('customers/edit/(d+)/', views.editcustomers), re_path('customers/delete/(d+)/', views.deletecustomers), ] #函数 #view.py from django.shortcuts import render,HttpResponse,redirect from app01.models import User,Role # Create your views here. def order(request): return HttpResponse("order...") def addorder(request): return HttpResponse("addorder...") def editorder(request,id): return HttpResponse("editorder...") def deleteorder(request,id): return HttpResponse("deleteorder...") def customers(request): return HttpResponse("customers...") def addcustomers(request): return HttpResponse("addcustomers...") def editcustomers(request,id): return HttpResponse("editcustomers...") def deletecustomers(request,id): return HttpResponse("deletecustomers...")
#urls.py path('login/',views.login), #views.py def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') user = User.objects.filter(name=user,pwd=pwd).first() if user: #把用户的信息保存在session中 request.session['user_id']=user.pk #查看当前等路人的权限 ,distinct()去重 permission=Role.objects.filter(user=user).values('permission__url').distinct() print(permission) #新建列表把权限进行循环,取到里面的每一个url permission_list = [] for item in permisssion: permission_list .append(item['permission__url']) # 把当前登录人的全县列表加入到列表中 request.session['permission_list']=permissions_list return HttpResponse('ok') return render(request,'login.html') #templates新建一个HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#form自带提交功能,不用写什么Ajax,还有,必须有name字段,没有name字段前段接收不到#} <form action="" method="post"> {% csrf_token %} 用户名<input type="text" name="user"> 密码<input type="text" name="pwd"> <input type="submit"> </form> </body> </html>
因为我们现在还没有设置中间件,所以我们在地址栏中输入地址还是可以进行访问,现在我们需要的就是设置中间件
#middlewares.py from django.utils.deprecation import MiddlewareMixin import re class PermissionMiddleWare(MiddlewareMixin): def process_request(self,request): current_path = request.path #设置白名单 for reg in ['/login/','/admin/*'] #search 用法:在整个current_path中查询reg ret = re.search(reg,current_path) if ret: return None #直接判断有没有登录 user_id = request.session.get('user_id') if not user_id: return redirect('/login/') #j校验数据 permission_list = reuqest.session.get('permission_list') for reg in permission_list: reg = '^%s$'%reg ret = re.search(reg,current_path) if ret: return None return HttpResponse('无权访问')
这就是django中中间件进行设置,我们可以判断有没有用户的登录,没有的话返回登录页面,有的话判断有没有权限,没有权限我们直接返回没有权限的认证,这就是django提供的方法
2.DRF中给我们提供的另一种方法,也就是利用token来进行用户的认证权限。DRF是我们用的比较多的一种方式,当我们前后端分离的时候我们给前端的传值必用Json数据,而DRF正好给我们提供了功能,当人还不仅是这一种功能,不多说,直接上代码
#models中 from django.db import models # Create your models here.
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
user_type_entry = (
(1, 'Delux'),
(2, 'SVIP'),
(3, 'VVIP')
)
user_type = models.IntegerField(choices=user_type_entry)
class UserToken(models.Model):
user = models.OneToOneField('User', on_delete=models.CASCADE)
token = models.CharField(max_length=128)
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
def __str__(self):
return self.name
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
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
# 外键字段
publish = models.ForeignKey(to="Publish", related_name="book", related_query_name="book_query", on_delete=models.CASCADE)
# 多对多字段
authors = models.ManyToManyField(to="Author")
进行数据的迁移创建超级用户以及创建urls
#数据的迁移 #makemigrations #migrate #urls
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'books/$',views.BookView.as_view({
'get':'list',
'post':'create'
})),
re_path(r'books/(?P<pk>d+)/$',views.BookView.as_view({
'put':'update',
'get':'retrieve',
'delete':'destroy'
})),
re_path(r'user/$',views.UserView.as_view()),
]
views.py from rest_framwork.viewsets import ModelViewSet from book_serializer import BookSerializer from.model import * class BookView(ModelViewSet):
#指定权限类
permission_class = [UserPerm] #指定用户校验类 authentication_class=[UserAuth] queryset=Book.objects.all() #指定序列化的类 serializer_class=BookSerializer
views.py class UserPerm(): message="您没有权限看该数据!" def has_permission(self,request,view): #3:代表是当前等路人的用户数字,是VIP还是VVIP,这里写死了 if request.user.user_type ==3: return True return False
#authentication.py from rest_framwork.authentication import BaseAuthentication from rest_framwork.exception import APIException from .model import * class UserAuth(BaseAuthentication): #我们的主要逻辑都在这里写 def aythenticate(self,request): #query_params这里存放我们所有的信息 user_token = request.query_params.get("token") try: token = UserToken.objects.get(token=user_token) return token.user,token.token except Exception: raise APIException("没有认证")
#book_serializer.py from rest_farmwork import serializers from ,model import * class BookSerializer(serializers.ModelSerializer); class Meta: model = Book fields=('title', 'price', 'author_list', 'publish_name', 'publish_city', ) #当查询结果是一个时用source查询,多个结果就需要我们自己构件方法 pulish_name=serializers.CharField(max_length=32,source='publish.name') publish_city=serializers.CharField(max_length=32,source='publish.city') author_list=serializers.SerializerMethodField() get_author_list(self,book_obj): author=[] for authors in book_obj.authors.all(): author.appent(authors.name) #如果还想要作者的年纪,可以直接取 author.appent(authors.age) return author
views.py class UserView(APIView): def post(self,request): #定义返回的数据格式 response={} #定规需要的用户的信息 fields={"username","password"} #用户信息的字典 user_info={} #request.data就是我的登录名和密码,判断这里是不是request.data.keys()的子集 if fields.issubset(set(request.data.keys())): for key in fields: user_info[key]=request.data[key] user_instance = User.objects.filter(**user_info).first() if user_instance is not None: access_token = get_token.generate_token() UserToken.objects.update_or_create(user=user_instance,defaults={'token':access_token}) response["status_code"] = 200 response["status_message"] = "登录成功" response["access_token"] = access_token response["user_role"] = user_instance.get_user_type_display() else: response["status_code"] = 201 response["status_message"] = "登录失败,用户名或密码错误" return JsonResponse(request)
现在我们如果不带着token值则会进不去,没有登录则进不去,权限没有也会进不去