Django之session驗證的三種姿勢
阿新 • • 發佈:2018-08-14
數據庫 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驗證的三種姿勢