django CBV装饰器 自定义django中间件 csrf跨站请求伪造 auth认证模块
CBV加裝飾器
第一種 @method_decorator(裝飾器) 加在get上
第二種 @method_decorator(login_auth,name='get') 加在類上
第三種 @method_decorator(login_auth) 加在dispatch上 3.7的要return super().dispatch
def login(request):if request.method == 'POST':username = request.POST.get('username')pwd = request.POST.get('pwd')if username == 'jason' and pwd == '123':request.session['name'] = 'jason'return redirect('/home/')return render(request,'login.html')from functools import wraps def login_auth(func):@wraps(func)def inner(request,*args,**kwargs):if request.session.get('name'):return func(request,*args,**kwargs)return redirect('/login/')return inner?導(dǎo)入裝飾器? ? 翻譯?decorators? 裝飾
from django.utils.decorators import method_decorator?
?被裝飾的類
@method_decorator(login_auth,name='get') #第二種 name參數(shù)必須指定 class MyHome(View):@method_decorator(login_auth) #第三種 get和post都會(huì)被裝飾def dispatch(self,request,*args,**kwargs):super().dispatch(request,*args,**kwargs)@method_decorator(login_auth) #第一種def get(self,request):return HttpResponse('get')def post(self,request):return HttpResponse('post')?
?
?
?自定義django中間件
?什么是中間件?
django請(qǐng)求生命周期完整版,中間件類似于django的門衛(wèi),數(shù)據(jù)在進(jìn)入和離開時(shí)都需要經(jīng)過中間件
中間件能干嘛?
控制用戶訪問頻率,全局登錄校驗(yàn),用戶訪問白名單,黑名單,反爬相關(guān)等
?用來幫你全局相關(guān)的功能校驗(yàn)
django默認(rèn)有7個(gè)中間件,但是django暴露給用戶可以自定義中間件并且里面可以寫五種方法?
?
中間件的使用(5個(gè)固定的方法)
process_request:請(qǐng)求來的時(shí)候從上往下依次執(zhí)行每一個(gè)中間件里面的process_request方法(如果沒有直接通過)
process_request(self,request)?
process_response:響應(yīng)走的時(shí)候會(huì)從下往上依次執(zhí)行每一個(gè)中間件里面的process_response方法(如果沒有直接通過)
process_response(self,request,response)return response?
process_view:路由匹配成功執(zhí)行視圖之前自動(dòng)觸發(fā)(從上往下依次執(zhí)行)
process_view(self, request, view_func, view_args, view_kwargs)?
process_exception:當(dāng)視圖函數(shù)報(bào)錯(cuò)了,自動(dòng)觸發(fā)(從下往上依次執(zhí)行)
process_exception(self,request,exception)?
process_template_response:視圖函數(shù)返回的對(duì)象有一個(gè)render()方法(或者表名對(duì)象是一個(gè)TemplateResponse對(duì)象或等價(jià)方法)(從上往下依次執(zhí)行)
process_template_response(self,request,response)return response
?
完整的流程圖
?
?
?自定義中間件
新建一個(gè)任意名字的文件夾,里面新建一個(gè)任意名字py文件
from django.utils.deprecation import MiddlewareMixin?
?
?
?
class MyMiddleware(MiddlewareMixi):def process_request(self,request):print(''我是第一個(gè)自定義中間件里面的process_request方法')#return HttpResponse('heieheihei')def process_response(self,request,response):print('我是第一個(gè)自定義中間件里面的process_response方法')return response #必須將response形參接收的數(shù)據(jù)返回,不然直接報(bào)錯(cuò)def process_view(self,request,view_func,view_args,view_kwargs):print('我是第一個(gè)自定義中間件里面的process_view方法')print(view_func.__name__,view_func)def process_exception(self,request,exception):print('我是第一個(gè)自定義中間件里面的process_exception方法')print(exception)def process_template_response(self,request,response):print('我是第一個(gè)自定義中間件里面的process_template_response方法')return response?
?
?自定義完之后再項(xiàng)目settings.py文件下引用
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',# 'app01.mymiddleware.mdzz.MyMiddleware', #自定義中間件1 應(yīng)用.文件夾.自定義py文件.自定義中間件類名# 'app01.mymiddleware.mdzz.MyMiddleware1' #自定義中間件2 ]?
?
?
csrf(跨站請(qǐng)求偽造)
由來:釣魚網(wǎng)站 拿到銀行轉(zhuǎn)賬的路徑,做一個(gè)跟銀行一模一樣的頁面,向銀行轉(zhuǎn)賬接口提交數(shù)據(jù),當(dāng)用戶在釣魚網(wǎng)站輸入對(duì)方賬戶名和轉(zhuǎn)賬金額之后,點(diǎn)擊發(fā)送,其實(shí)內(nèi)部是將對(duì)方賬戶換成了釣魚網(wǎng)站的造假人員的賬戶。造成你轉(zhuǎn)賬轉(zhuǎn)錯(cuò)賬戶的情況
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script><link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"><script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </head> <body> <h1>正經(jīng)的網(wǎng)站</h1> <form action="/index3/" method="post"> {# {% csrf_token %}#}<p>username:<input type="text" name="username"></p><p>money:<input type="text" name="money"></p><p>others:<input type="text" name="others"></p><input type="submit"> </form> </body> </html> 正常頁面?
釣魚網(wǎng)站提交連接也是銀行的轉(zhuǎn)賬接口
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script><link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"><script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </head> <body> <h1>釣魚網(wǎng)站</h1> <form action="http://127.0.0.1:8000/transfer/" method="post"><p>username:<input type="text" name="username"></p><p>money:<input type="text" name="money"></p><p>others:<input type="text"></p><input type="text" name="others" value="jason" style="display:none"><input type="submit"> </form> </body> </html> 釣魚頁面?
?
如何區(qū)分釣魚網(wǎng)站和正經(jīng)網(wǎng)站?在正經(jīng)網(wǎng)站返回頁面的時(shí)候,在form表單中偷偷塞一個(gè)特殊的字符串,后端記下該頁面對(duì)應(yīng)的字符串的值,等用戶發(fā)post請(qǐng)求來的時(shí)候,我先去校驗(yàn)特殊的字符串是否匹配
如何去寫這個(gè)特殊的字符串?
模板語法有一個(gè)固定的寫法? ?必須寫在form表單內(nèi)
{% csrf_token %}?
表單中偷偷塞的特殊的字符串
{% csrf_token %} <input type='hidden' name='csrfmiddlewaretoke' value='"2vzoo1lmSWgLTdI2rBQ4PTptJQKRQTRwnqeWRGcpdAQGagRp8yKg8RX2PdkF4aqh">Ps:value是動(dòng)態(tài)生成的,每一次刷新都不一樣?
?
ajax中如何設(shè)置csrf_token? 把k和v放在data里面
<form action="/index3/" method="post"> {# {% csrf_token %}#}<p>username:<input type="text" name="username"></p><p>money:<input type="text" name="money"></p><p>others:<input type="text" name="others"></p><input type="submit"> </form> <button>ajax</button> <script>$('button').click(function () {$.ajax({url:'',type:'post',data:{'name':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},success:function (data) {console.log(data)}})}) </script>? 第二種ajax提交 data:{'csrfmiddlewaretoken':'{{ csrf_token}}'}
?
csrf_token導(dǎo)入
form django.views.decorators.csrf import csrf_exempt,csrf_protect?
?
csrf 裝飾FBV
不校驗(yàn)csrf
@csrf_exempt def index1(request):return HttpResponse('ok')?
校驗(yàn)csrf
@csrf_protect def index2(request):return HttpResonse('ok')?
?
csrf裝飾給CBV?
先導(dǎo)入裝飾器語法
from django.utils.decorators import method_decorator?
校驗(yàn)csrf
@method_decorator(csrf_protect,name='post') #第三種 class Index3(View):@method_decorator(csrf_protect) #第二種def dispatch(self,request,*args,**kwargs):super().dispatch(request,*args,**kwargs)def get(self,request):return HttpResponse('get')@method_decortaor(csrf_protect) #第一種def post(self,request):return HttpResponse('post')?
不校驗(yàn)csrf (只有兩種 每種都是全都不校驗(yàn))
@method_decorator(csrf_exempt,name='dispatch') #第二種 class Index3(View):@method_decorator(csrf_exempt) #第一種def dispatch(slef,request,*args,**kwargs):super().dispatch(request,*args,**kwargs)def get(self,request):return HttpResponse('get')def post(self,request):return HttpResponse('post')?
?
csrf裝飾CBV需要注意
csrf_protect 跟正常的CBV裝飾器一樣 三種
csrf_exempt 只能有下面兩種方式
@method_decorator(csrf_exempt,name='dispatch') #一種
class Index3(View):
#@method_decorator(csrf_exempt) #二種
def dispatch(self,request,*args,**kwargs):
super().dispatch(request,*args,**kwargs)
其實(shí)都是給dispatch加
?
Auth認(rèn)證模塊
執(zhí)行數(shù)據(jù)庫(kù)遷移的那兩命令式,即使我們沒有建表,django也會(huì)創(chuàng)建好多張表 auth_user表存放的用戶相關(guān)的數(shù)據(jù)
?
auth_user表記錄的添加
創(chuàng)建超級(jí)用戶(不可手動(dòng)插入,因?yàn)槊艽a是加密的)
可以使用命令行createsuperuser 會(huì)讓你輸入用戶名和密碼 但是都是明文輸入
簡(jiǎn)單使用auth認(rèn)證 auth.authenticate(校驗(yàn)條件)
from django.contrib import auth def login(request):if request.method == 'POST':name = request.POST.get('name')pwd = request.POST.get('pwd')#models.User.objects.filter(username=username,password=pwd)user_obj = auth.authenticate(request,username=username,password=pwd)#authenticate 驗(yàn)證if user_obj:#設(shè)置用戶狀態(tài)#request.session['name'] = 'jason'auth.login(request,user_obj) #一旦記錄了 ,可以在任意的地方通過request.user獲取到當(dāng)前登錄對(duì)象return HttpResponse('ok')return render(request,'auth_login.html')?
只要登錄成功執(zhí)行了auth.login(request,user_obj)
之后在其他任意的視圖函數(shù)中都通過request.user獲取當(dāng)前登錄用戶對(duì)象
如果沒有執(zhí)行auth.login??
request.user打印出來的是匿名用戶
如何判斷request.user用戶是否通過auth.login登錄呢?
request.user.is_authenticated()
?為何auth.login之后,其他視圖函數(shù)中就可以通過request.user拿到當(dāng)前登錄對(duì)象呢?
其實(shí)就是把用戶信息放到django_session表
?
注銷 auth.logout(request)
def auth_logout(request):auth.logout(request) #等價(jià)于request.session.flush()return HttpResponse('ok')?
?
需要找到這張表
from django.contrib.auth.models import User?
?注冊(cè) User.objects.create_user 普通用戶 User.objectes.create_superuser 超級(jí)用戶
def auth_register(request):if request.method = 'POST':username = request.POST.get('username')password = request.POST.get('password')user_obj = auth.authenticate(request,username=username)#校驗(yàn)用戶if user_obj:return HttpResponse('當(dāng)前用戶已存在')#User.objectes.create(username=username,password=password) 不能再用create創(chuàng)建#User.objects.create_user(username=username,password=password) #創(chuàng)建普通用戶User.objects.create_superuser(username=username,password=password,email='123@163.com') #創(chuàng)建超級(jí)用戶return render(request,'auth_register.html')?
?
?更改密碼? request.user.check_password('密碼') 校驗(yàn)密碼 request.user.set_password('新密碼') 設(shè)置新的密碼 request.user.save() 保存
def auth_password(request):print(request.user.password) #密文is_res = request.user.check_password('jason123') #校驗(yàn)密碼是否一致if is_res:request.user.set_password('666') #設(shè)置新密碼request.user.save() #修改密碼必須save保存 不然無效return HttpResponse('ok')?
?
?裝飾器校驗(yàn)是否登錄及跳轉(zhuǎn)
?auth裝飾器
from django.contrib.auth.decorators import login_required?
?被裝飾函數(shù)
@login_required(login_url='/login/',redirect_field_name = 'old') #沒登錄會(huì)跳轉(zhuǎn)login頁面,并且后面會(huì)拼接上你上一次想訪問的頁面路徑/login/?next=/你想訪問的路徑/ 可以通過參數(shù)修改next鍵名 def auth_home(request):return HttpResponse('home必須登錄才能訪問')?
如果我所有視圖函數(shù)都需要裝飾并跳轉(zhuǎn)到login頁面,那么我要寫好多份 為了一勞永逸
#可以在項(xiàng)目配置文件中指定auth校驗(yàn)登錄不合法統(tǒng)一跳轉(zhuǎn)到某一個(gè)路徑 LOGIN_URL = '/login/' #全局配置?
?
自定義模型表引用auth功能
如何擴(kuò)張auth_user表?
一對(duì)一關(guān)聯(lián)(不推薦)
from django.contrib.auth.model import Userclass UserDetail(models.Model):phone = models.CharField(max_length=11)user = models.OnoToOneField(to=User) #User表在之前創(chuàng)建了 所以可以直接寫to=User?
?
面向?qū)ο蟮睦^承
導(dǎo)入語法
from django.contrilb.auth.models import User,AbstractUser?
?
class UserInfo(AbstractUser):phone = models.CharField(max_length=32)avatar = models.CharField(max_length=32)?
?
告訴django不在使用默認(rèn)的auth_user,而使用我們自己定義的表
語法:AUTH_USER_MODEL= ‘a(chǎn)pp名.models里面對(duì)相應(yīng)的模型表名’
在項(xiàng)目settings.py文件中配置
AUTH_USER_MODEL= 'app01.UserInfo'?
?
自定義認(rèn)證系統(tǒng)默認(rèn)使用的數(shù)據(jù)表之后,我們我們就可以像使用默認(rèn)的auth_user表那樣使用我們的UserInfo表了
庫(kù)里面也沒有auth_user表了,原來auth表的操作方法,現(xiàn)在全部用自定義的表均可實(shí)現(xiàn)
?
轉(zhuǎn)載于:https://www.cnblogs.com/lakei/p/11048141.html
總結(jié)
以上是生活随笔為你收集整理的django CBV装饰器 自定义django中间件 csrf跨站请求伪造 auth认证模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pageContext对象
- 下一篇: 以VMware workstation1