中間件、Auth認證模塊

中間件、Auth認證模塊

CVB加裝飾器

# 寫一個裝飾器驗證session
from functions 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

第一種

from django.views import View
from django.utils.decorators import method_decorator

class MyHome(View):
    def dispatch(self,request,*args,**kwargs)
        super().dispatch(reauest,*args,**kwargs)
    
    @method_decorator(login_auth)
    def get(self,request):
        return HttpResponse('ok')

第二種

from django.views import View
from django.utils.decorators import method_decorator

@method_decorator(login_auth,name='get')  # name參數必須指定
class MyHome(View):
    def dispatch(self,request,*args,**kwargs)
        super().dispatch(reauest,*args,**kwargs)
    
    
    def get(self,request):
        return HttpResponse('ok')

第三種

from django.views import View
from django.utils.decorators import method_decorator

class MyHome(View):
    @method_decorator(login_auth)  # get和post都會被裝飾
    def dispatch(self,request,*args,**kwargs)
        super().dispatch(reauest,*args,**kwargs)
    
    
    def get(self,request):
        return HttpResponse('ok')

中間件

中間件用於在全局範圍內改變Django的輸入和輸出,須要謹慎使用,使用不當會影響性能html

簡單來講就是在視圖函數執行以前和執行以後均可以作一些額外的操做,能夠用來控制用戶訪問頻率,全局登陸校驗,用戶訪問白名單,黑名單等python

Django默認的三個中間件:

  • Csrf
  • Session
  • Auth

中間件能夠定義五個方法

  • process_request(self,request)
  • process_response(self,request,response)
  • process_view(self,request,view_args,view_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self,request,exception)

以上方法的返回值能夠是None或一個HTTPResponse對象,若是是None,則繼續按照django定義的規則向後繼續執行,若是是HTTPResponse對象,則直接將該對象返回給用戶ajax

如何定義?

在應用下新建一個文件夾,在文件夾下新建一個py文件,而後在settings配置文件中註冊django

process_request執行順序

須要一個參數request,能夠對request對象進行一系列的操做,後續也能夠在視圖函數中經過相同的方式獲取值後端

1.中間件的process_request方法是在執行視圖函數以前執行的
2.當配置多箇中間件時,會按照MIDDLEWARE中的註冊順序,也就是列表的索引值,從前到後依次執行的
3.不一樣中間件之間傳遞的request都是同一個對象

process_response執行順序

須要兩個形參,request和response,response是視圖函數返回的HTTPResponse對象(django後臺處理後給出的一個具體的視圖)瀏覽器

1.中間件的process_response方法是在視圖函數以後執行的
2.當配置多箇中間件時,會按照MIDDLEWARE的註冊順序倒序執行的
3.不一樣中間件之間傳遞的request都是同一個對象

process_view執行順序

須要四個參數:session

  • request:是HTTPResponse對象
  • view_func:是diango即將使用的函數(它是實際的函數對象)
  • view_args:是將傳遞給函數的位置參數的列表
  • view_kwargs:是將傳遞給視圖函數的關鍵字參數的字典
1.diango會在路由系統以後,視圖函數以前調用process_view方法
2.按照MIDDLEWARE中的註冊順序從前日後順序執行

process_exception執行順序

須要兩個參數:app

  • request:是HTTPResponse對象
  • exception:是視圖函數異常產生的Exception對象
1.中間件的process_exception方法是在視圖函數以後執行的
2.當配置多箇中間件時,會按照MIDDLEWARE的註冊順序倒序執行的

若是視圖函數中無異常,該方法不執行函數

process_template_response(用的比較少)執行順序

須要兩個參數:工具

  • request:是HTTPResponse對象
  • response:是TemplateResponse對象(由視圖函數產生或中間件產生)
在視圖函數執行完後當即執行,順序是倒序,可是有一個條件,那就是視圖函數返回的對象有一個render()方法

中間件執行流程總結:

請求到達中間件以後,先按照正序執行每一個註冊中間件的process_request方法,process_request方法返回的值是None,就依次執行,若是返回的值是HttpResponse對象,再也不執行後面的process_request方法,而是執行當前對應中間件的process_response方法(注意不是掉頭執行全部的process_response方法),將HttpResponse對象返回給瀏覽器。也就是說:若是MIDDLEWARE中註冊了6箇中間件,執行過程當中,第3箇中間件返回了一個HttpResponse對象,那麼第4,5,6中間件的process_request和process_response方法都不執行,順序執行3,2,1中間件的process_response方法。

process_request方法都執行完後,匹配路由,找到要執行的視圖函數,先不執行視圖函數,先執行中間件中的process_view方法,process_view方法返回None,繼續按順序執行,全部process_view方法執行完後執行視圖函數。假如中間件3 的process_view方法返回了HttpResponse對象,則4,5,6的process_view以及視圖函數都不執行,直接從最後一箇中間件,也就是中間件6的process_response方法開始倒序執行。

process_template_response和process_exception兩個方法的觸發是有條件的,執行順序也是倒序

csrf(跨站請求僞造)

form表單中跨站請求僞造

<form method='post'>
    {% csrf_token %}
</form>

ajax中設置csrf_token

將隨機產生的字符串放進數據傳給後端,鍵固定,值以屬性查找的方式找到

{% csrf_token %}
<button>
    ajax
</button>
<script>
    $('button').click(function){
        $.ajax({
            url:'',
            type:'post',
            data:{'name':'lucas','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},  //第一種
             data:{'name':'lucas','csrfmiddlewaretoken':'{{ csrf_token }}'},   //第二種
            success:function(data){
                console.log(data)
            }
        })
    }
</script>

csrf_token局部使用

# 只想給某個視圖函數加上csrf校驗
from django.views.decorators.csrf import csrf_exempt,csrf_protect

# 局部禁用
@csrf_exempt
def index(request):
    pass


# 局部使用
@csrf_procept
def login(request):
    pass


# CBV比較特殊,不能單獨加在某個方法上
# 只能加在類上或dispatch方法上

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect


@method_decorator(csrf_exempt,name='dispatch')  # 第一種
class Csrf_Token(View):
  @method_decorator(csrf_exempt)  # 第二種
  def dispatch(self,request,*args,**kwargs):
    res = super().dispatch(request,*args,**kwargs)
    return res
  @method_decorator(csrf_exempt)  # 這裏這麼寫不行!!!
  def get(self,request):
    pass
  def post(self,request):
    pass

注意:csrf_protect 跟正常的CBV裝飾器同樣 三種

Auth認證模塊

auth_user表記錄的添加

  • 建立超級用戶(不可手動插入,由於密碼是加密的)
  • 簡單使用auth認證
from django.contrib import auth
def login(request):
    if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(request,username=name,password=pwd) # 判斷用戶是否存在
        if user:
            return redirect('/home/')
    return render(request,'login.html')

auth存儲session

if user:
    auth.login(request,user)  # 一旦記錄了,能夠在任意地方經過request.user獲取當前登入對象

判斷是否登入

def index(request):
    print(request.user.is_authenticated())  # 判斷當前用戶是否已經登入
    print(request.user,type(request.user))  # 獲取當前登入用戶對象

刪除session值

def logout(request):
    auth.logout(request)  # request.session.flush

建立用戶

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)
        if user_obj:
            return HttpResponse('當前用戶已存在')
        # models.User.objects.create(username=username,password=password)
        # User.objects.create(username=username,password=password)  # 不能再用create建立
        # User.objects.create_user(username=username,password=password)  # 建立普通用戶
        User.objects.create_superuser(username=username,password=password,email='123@163.com')  # 建立超級用戶
    return render(request,'auth_register.html')

修改密碼

def auth_password(request):
    print(request.user.password)
    is_res = request.user.check_password('jason123')  # 校驗密碼是否一致
    if is_res:
        request.user.set_password('666')  # 設置新密碼
        request.user.save()  # 修改密碼必須save保存  否則無效
    return HttpResponse('ok')

裝飾器工具

局部配置

from django.contrib.auth.decorators import login_required

@login_required(login_url='/login/')
def home(request):
    return HttpResponse('ok')

自定義登入的URL

須要在settings文件中修改

# auth自動跳轉
LOGIN_URL = '/login/'  # 這裏配置項目登入頁面的路由,原路徑仍是要本身判斷

擴展默認的auth_user表

經過繼承內置的AbstractUser類,來定義一個本身的Model類

既能根據項目需求靈活的設計用戶表,又能使用Django強大的認證系統

from django.db import models
from django.contrib.auth.models import User,AbstractUser
# Create your models here.
# 第一種擴展字段的方式(瞭解便可)
# class Userinfo(models.Model):
#     phone = models.CharField(max_length=32)
#     avatar = models.CharField(max_length=32)
#     ab = models.OneToOneField(to=User)

class Userinfo(AbstractUser):
    phone = models.CharField(max_length=32)
    avatar = models.CharField(max_length=32)

注意:擴展了內置的auth_user表以後,必定要在settings中告訴Django

# AUTH_USER_MODEL = 'app名.models裏面對應的模型表名'
AUTH_USER_MODEL = 'app01.Userinfo'

最後補一張請求流程圖

相關文章
相關標籤/搜索