1. 程式人生 > >使用者登入許可權彙總

使用者登入許可權彙總

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值則會進不去,沒有登入則進不去,許可權沒有也會進不去