Django之session驗證的三種姿式

一.什麼是session

session是保存在服務端的鍵值對,Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_session 表中html

二.FVB中使用裝飾器進行session驗證

認證裝飾器:python

# 登錄驗證
def auth(func):
 '''判斷是否登陸裝飾器'''
    def inner(request, *args, **kwargs):
        ck = request.session.get("username")
		'''若是沒有登錄返回到login.html'''
        if not ck:
            return redirect("/login.html")
        return func(request, *args, **kwargs)
    return inner

 在須要認證的函數執行前加上裝飾器認證便可,實際中應用以下:數據庫

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    else:
        username = request.POST.get("user")
        pwd = request.POST.get("pwd")
        pwd = md5(pwd)
        dic = {"flag":False}
        obj = User.objects.filter(username=username, pwd=pwd).first()
        if obj:
            request.session["username"] = username
            return redirect("/index.html")
        else:
            print(dic)
            return HttpResponse(json.dumps(dic))

@auth
def index(request):
    user = request.session.get("username")
    business = Business.objects.all().values("name")
    host_list = Host.objects.all().values("id","host","port","business__name")
    username = User.objects.all().values("username")
    return render(request, 'index.html', {'host_list':host_list,"business":business,"user":user,"username":username})
	
@auth
def addhost(request):
    business = Business.objects.all().values("name")
    if request.method == "POST":
        user = request.session.get("username")
        host = request.POST.get("host")
        port = request.POST.get("port")
        select_business = request.POST.get("business")
        business_id = Business.objects.filter(name=select_business).values("id")[0]
        host = Host.objects.create(host=host,
                                  port=port,
                                  business_id=business_id["id"])
        # host.business.add(*business)
        return render(request, "index.html")

    return render(request, "index.html", {"business":business})
	
@auth
def up_business(request):
    if request.method == "POST":
        user = request.session.get("username")
        host= request.POST.get("host")
        port= request.POST.get("port")
        business_name = request.POST.get("business")
        username = request.POST.get("username")
        print(host,port,business_name,username)
        return render(request,"保存成功")

 三.CBV中使用類繼承的方式進行session認證

  • cbv是 class based view(基於類)
  • cbv基於dispatch進行反射,get獲取,post提交
  • 應用場景:登陸認證(繼承dispatch,在dispatch裏作session驗證)

CBV第一種方式繼承

1.單繼承

掃盲:(繼承的時候,必定要清楚self是哪一個類實例化出來的對象,下例,self爲B實例化的對象,任何屬性優先從本身裏面找,找不到在去父類裏找)django

class A(object):
    def aaa(self):
        print('from A')
    def bbb(self):
        self.aaa()
 
class B(A):
    def aaa(self):
        print('from B')
 
c = B()
c.aaa()

應用:
json

from django.views import View
class BaseView(View):
    def dispatch(self, request, *args, **kwargs):  # 繼承父類的dispatch,由於父類裏有返回值,因此也要有return
        if request.session.get('username'):
            response = super(BaseView, self).dispatch(request, *args, **kwargs)
            return response
        else:
            return redirect('/login.html')
 
class IndexView(BaseView):
 
    def get(self, request, *args, **kwargs):
        return HttpResponse(request.session['username'])

 2.多繼承(繼承順序從左到右)

class BaseView(object):
    def dispatch(self, request, *args, **kwargs):
        if request.session.get('username'):
            response = super(BaseView,self).dispatch(request, *args, **kwargs)
            return response
        else:
            return redirect('/login.html')
 
class IndexView(BaseView,View):#先去找BaseView,BaseView中未定義在去找View
 
    def get(self,request,*args,**kwargs):
        return HttpResponse(request.session['username'])

 CBV第二種方式裝飾器

from django.utils.decorators import method_decorator
 
def auth(func): #定義裝飾器
    def inner(request,*args,**kwargs):
        if request.session.get('username'):
            obj = func(request,*args,**kwargs)
            return obj
        else:
            return redirect('/login.html')
    return inner
 
@method_decorator(auth,name='get')  #放在類頂部就須要method_decorator這個裝飾器
class IndexView(View):
 
    @method_decorator(auth) #放在dispatch上就至關於全局都須要通過認證
    def dispatch(self, request, *args, **kwargs):
        if request.session.get('username'):
            response = super(IndexView,self).dispatch(request, *args, **kwargs)
            return response
        else:
            return redirect('/login.html')
 
    @method_decorator(auth)
    def get(self,request,*args,**kwargs):
        return HttpResponse(request.session['username'])
 
    @method_decorator(csrf_exempt)  # 無效 csrf 放到post函數上的裝飾器,是無效的,須要放到dispath上或者類上
    def post(self,request,*args,**kwargs):
        return HttpResponse(request.session['username'])

 四.中間件middleware

以下是django的生命週期瀏覽器

 以下爲中間件的執行順序cookie

 - 中間件執行時機:請求到來,請求返回時
  - 中間件是一個類:
  def process_request(self,request):
    print('m2.process_request')session

  def process_response(self,request, response):
    print('m2.prcess_response')
    return response

    - 應用:
    - 請求日誌
    - 用戶登陸認證app

Django根目錄新建md文件夾,新建Middleware.py文件函數

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    '''先執行request,而後到url路由,url以後返回到最上方,在執行view,若是出現錯誤就直接到response上,執行完,到真正到視圖,若是有問題就
    執行exception,從下至上查找,若是找到exception就直接執行exception的return在走response返回用戶
    每一箇中間件中,4個方法不須要都寫.
    '''
    def process_request(self,request):

        if request.path_info == "/login.html":
            return None
        user_info = request.session.get("username")
        if not user_info:
            return redirect("/login.html")

 注:新的django版本可能不存在MiddlewareMixin,須要手動寫一下這個類進行繼承

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response

class M1(MiddlewareMixin):

    def process_request(self,request):

        if request.path_info == "/login.html":
            return None
        user_info = request.session.get("username")
        if not user_info:
            return redirect("/login.html")

 settings裏配置:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'md.Middleware.M1',
]

WSGI_APPLICATION = 'BBS.wsgi.application'

SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 引擎(默認)

SESSION_COOKIE_NAME = "sessionid"  # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
SESSION_COOKIE_PATH = "/"  # Session的cookie保存的路徑(默認)
SESSION_COOKIE_DOMAIN = None  # Session的cookie保存的域名(默認)
SESSION_COOKIE_SECURE = False  # 是否Https傳輸cookie(默認)
SESSION_COOKIE_HTTPONLY = True  # 是否Session的cookie只支持http傳輸(默認)
SESSION_COOKIE_AGE = 1209600  # Session的cookie失效日期(2周)(默認)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 是否關閉瀏覽器使得Session過時(默認)
SESSION_SAVE_EVERY_REQUEST = True  # 是否每次請求都保存Session,默認修改以後才保存(默認)
相關文章
相關標籤/搜索