1. 程式人生 > >Django之session驗證的三種姿勢

Django之session驗證的三種姿勢

數據庫 render _id sed security war tin lec div

一.什麽是session

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

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

認證裝飾器:

1 2 3 4 5 6 7 8 9 10 # 登陸驗證 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

在需要認證的函數執行前加上裝飾器認證即可,實際中應用如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 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實例化的對象,任何屬性優先從自己裏面找,找不到在去父類裏找)

1 2 3 4 5 6 7 8 9 10 11 12 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()

應用:

1 2 3 4 5 6 7 8 9 10 11 12 13 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.多繼承(繼承順序從左到右)

1 2 3 4 5 6 7 8 9 10 11 12 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第二種方式裝飾器

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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的生命周期

技術分享圖片

如下為中間件的執行順序

技術分享圖片

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

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

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

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 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,需要手動寫一下這個類進行繼承

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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裏配置:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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,默認修改之後才保存(默認)

Django之session驗證的三種姿勢