Python Django 生命週期 中間鍵 csrf跨站請求僞造 auth認證模塊 settings功能插拔式源碼

一 django 生命週期html

 

二 django中間鍵前端

1.什麼是中間鍵web

  官方的說法:中間件是一個用來處理Django的請求和響應的框架級別的鉤子。它是一個輕量、低級別的插件系統,用於在全局範圍內改變Django的輸入和輸出。每一箇中間件組件都負責作一些特定的功能。ajax

        簡單來講就至關於django門戶,保安:它本質上就是一個自定義類,類中定義了幾個方法。數據庫

        請求的時候須要先通過中間件才能到達django後端(urls,views,templates,models);django

        響應走的時候也須要通過中間件才能到達web服務網關接口後端

2.中間件用途:瀏覽器

#1.網站全局的身份校驗,訪問頻率限制,權限校驗...只要是涉及到全局的校驗你均可以在中間件中完成
#2.django的中間件是全部web框架中 作的最好的微信

3.注意:cookie

  django默認有七個中間件,可是django暴露給用戶能夠自定義中間件而且裏面能夠寫五種方法

  默認的七個中間鍵

 

 

 五個方法及執行時機:

##下面的從上往下仍是從下往上都是按照註冊系統來的##
#
須要咱們掌握的方法有 1.process_request(self,request)方法 規律: 1.請求來的時候 會通過每一箇中間件裏面的process_request方法(從上往下) 2.若是方法裏面直接返回了HttpResponse對象 那麼再也不往下執行,會直接原路返回並執行process_response()方法(從下往上) 基於該特色就能夠作訪問頻率限制,身份校驗,權限校驗 2. process_response(self,request,response)方法 規律: 1.必須將response形參返回 由於這個形參指代的就是要返回給前端的數據 2.響應走的時候 會依次通過每個中間件裏面的process_response方法(從下往上) #須要瞭解的方法 3. process_view(self,request,view_func,view_args,view_kwargs) 1.在路由匹配成功執行視圖函數以前 觸發執行(從上往下) 4.process_exception(self, request, exception) 1.當你的視圖函數報錯時 就會自動執行(從下往上) 5.process_template_response(self, request, response) 1.當你返回的HttpResponse對象中必須包含render屬性纔會觸發(從下往上) def index(request): print('我是index視圖函數') def render(): return HttpResponse('什麼鬼玩意') obj = HttpResponse('index') obj.render = render return obj 總結:你在書寫中間件的時候 只要形參中有repsonse 你就順手將其返回 這個reponse就是要給前端的消息

4.如何自定義中間件

#1.先建立與app應用同級目錄的任意文件夾

#2.在文件夾內建立任意名py文件

#3.在py文件中編寫自定義中間鍵(類)注意幾個固定語法和模塊導入

1.py文件中必需要導入的模塊 from django.utils.deprecation import MiddlewareMixin 2.自定義中間鍵的類必需要繼承的父類 MiddlewareMixin 3.總體例: 
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class MyMdd(MiddlewareMixin):
def process_request(self,request):
print('我是第一個中間件裏面的process_request方法')


def process_response(self,request,response):
print('我是第一個中間件裏面的process_response方法')
return response

def process_view(self,request,view_func,view_args,view_kwargs):
print(view_func)
print(view_args)
print(view_kwargs)
print('我是第一個中間件裏面的process_view方法')

def process_exception(self, request, exception):
print('我是第一個中間件裏面的process_exception')

def process_template_response(self, request, response):
print('我是第一個中間件裏面的process_template_response')
return response

#4.settings.py文件中配置自定義的中間件(總體示例)

三 csrf跨站請求僞造

1.釣魚網站

#1.經過製做一個跟正兒八經的網站如出一轍的頁面,騙取用戶輸入信息 轉帳交易
從而作手腳
  轉帳交易的請求確確實實是發給了中國銀行,帳戶的錢也是確確實實少了
  惟一不同的地方在於收款人帳戶不對

#2.內部原理
  在讓用戶輸入對方帳戶的那個input上面作手腳
  給這個input不設置name屬性,在內部隱藏一個實現寫好的name和value屬性的input框
  這個value的值 就是釣魚網站受益人帳號

#3.防止釣魚網站的思路
  網站會給返回給用戶的form表單頁面 偷偷塞一個隨機字符串
  請求到來的時候 會先比對隨機字符串是否一致 若是不一致 直接拒絕(403)

該隨機字符串有如下特色
 1.同一個瀏覽器每一次訪問都不同
 2.不一樣瀏覽器絕對不會重複

2.實際用法

#這時候就不須要註釋settings.py文件中的中間件了

#1.經過form表單提交數據實際用法

1.form表單發送post請求的時候 須要你作得僅僅書寫一句話 {% csrf_token %} 示例: <form action="" method="post"> {% csrf_token %} <p>username:<input type="text" name="username"></p>
    <p>password:<input type="text" name="password"></p>
    <input type="submit">
</form>

#2.經過ajax提交數據的三種用法

1.如今頁面上寫{% csrf_token %},利用標籤查找 獲取到該input鍵值信息(不推薦) $('[name=csrfmiddlewaretoken]').val() 例: {'username':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()} 2.直接書寫'{{ csrf_token }}' 例:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'} 3.你能夠將該獲取隨機鍵值對的方法 寫到一個js文件中,以後只須要導入該文件便可具體操做以下 #1.static新建一個js任意名文件 存放如下代碼 見其餘代碼 #2.在html文件中引入剛纔的js文件(以setjs.js文件 爲例)
<script src="{% static 'setjs.js' %}"></script>
#3.直接正常編寫ajax代碼
 整體示例 $('#b1').click(function () { $.ajax({ url:'', type:'post', // 第一種方式 data:{'username':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}, // 第二種方式 data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}, // 第三種方式 :直接引入js文件 data:{'username':'jason'}, success:function (data) { alert(data) } })
View Code

第三種方式的js文件代碼

function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
View Code

3.處理不一樣場景的校驗方式(當settings.py的中間件 不鍵註釋時:全局校驗,註釋時:全局不校驗)

#1.當你網站全局都須要校驗csrf的時候 有幾個不須要校驗該如何處理(全局校驗,單個不校驗)

#1.首先導入模塊
from django.views.decorators.csrf import csrf_exempt,csrf_protect #給fbv加裝飾器:@csrf_exempt
@csrf_exempt def login(request): return HttpResponse('login')

#2.當你網站全局不校驗csrf的時候 有幾個須要校驗又該如何處理(全局不校驗,單個校驗)

#1.首先導入模塊
from django.views.decorators.csrf import csrf_exempt,csrf_protect #給fbv加裝飾器:@csrf_protect
@csrf_protect def show(request): return HttpResponse('lll')

#3.給cbv裝飾的時候

from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect # 這兩個裝飾器在給CBV裝飾的時候 有必定的區別
若是是csrf_protect 那麼有三種方式 # 第一種方式 # @method_decorator(csrf_protect,name='post') # 有效的
class MyView(View): # 第三種方式
    # @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs): res = super().dispatch(request, *args, **kwargs) return res def get(self, request): return HttpResponse('get') # 第二種方式
    # @method_decorator(csrf_protect) # 有效的
    def post(self, request): return HttpResponse('post') 若是是csrf_exempt 只有兩種(只能給dispatch裝) 特例 @method_decorator(csrf_exempt, name='dispatch')  # 第二種能夠不校驗的方式
class MyView(View): # @method_decorator(csrf_exempt) # 第一種能夠不校驗的方式
    def dispatch(self, request, *args, **kwargs): res = super().dispatch(request, *args, **kwargs) return res def get(self, request): return HttpResponse('get') def post(self, request): return HttpResponse('post')

拓展:cbv登陸裝飾器的幾種方式

CBV加裝飾器 # @method_decorator(login_auth,name='get') # 第二種 name參數必須指定
class MyHome(View): @method_decorator(login_auth) # 第三種 get和post都會被裝飾
    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')

四 Auth認證模塊

1.什麼是Auth模塊:Auth模塊是Django自帶的用戶認證模塊,它默認使用 auth_user 表來存儲用戶數據(能夠經過其餘操做來使用別的表)。主要解決開發一個網站用戶系統的註冊、用戶登陸、用戶認證、註銷、修改密碼等功能。執行數據庫遷移命令以後  會生成不少表  其中的auth_user是一張用戶相關的表格。

2.如何使用

#1.基本使用

#導入模塊
from django.contrib import auth 1.查詢(條件至少要爲2個) :對象=auth.authenticate(條件1,條件2) user_obj = auth.authenticate(username=username,password=password)  # 必需要用 由於數據庫中的密碼字段是密文的 而你獲取的用戶輸入的是明文

2.記錄狀態:auth.login(request,對象) auth.login(request,user_obj) # 將用戶狀態記錄到session中

3.註銷:auth.logout(request) auth.logout(request) # request.session.flush()

4.判斷用戶是否登陸 ,若是執行過了 auth.login(request,對象) 結果就爲Ture print(request.user.is_authenticated) 5.登陸認證裝飾器2種方式:校驗用戶是否登陸 第一種方式: from django.contrib.auth.decorators import login_required @login_required(login_url='/xxx/')  # 局部配置,'/xxx/'爲登陸視圖函數的url地址
def index(request): pass 第二種方式: from django.contrib.auth.decorators import login_required @login_required def index(request): pass settings.py文件中配置 LOGIN_URL = '/xxx/'  # 全配置,'/xxx/'爲登陸視圖函數的url地址
from django.contrib import auth 1.密碼: #驗證密碼是否正確:request.user.check_password(密碼)
is_right = request.user.check_password(old_password) #修改密碼
request.user.set_password(new_password) request.user.save() # 修改密碼的時候 必定要save保存 不然沒法生效 #示例 # 修改用戶密碼
@login_required # 自動校驗當前用戶是否登陸 若是沒有登陸 默認跳轉到 一個莫名其妙的登錄頁面
def set_password(request): if request.method == 'POST': old_password = request.POST.get('old_password') new_password = request.POST.get('new_password') # 先判斷原密碼是否正確
        is_right = request.user.check_password(old_password)  # 將獲取的用戶密碼 自動加密 而後去數據庫中對比當前用戶的密碼是否一致
        if is_right: print(is_right) # 修改密碼
 request.user.set_password(new_password) request.user.save() # 修改密碼的時候 必定要save保存 不然沒法生效
    return render(request,'set_password.html') 2.建立用戶 from django.contrib.auth.models import User # User.objects.create_user(username =username,password=password) # 建立普通用戶
User.objects.create_superuser(username =username,password=password,email='123@qq.com')  # 建立超級用戶 郵箱必填
示例: from django.contrib.auth.models import User def register(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') user_obj = User.objects.filter(username=username) if not user_obj: # 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@qq.com')  # 建立超級用戶
    return render(request,'register.html')
密碼和建立用戶

#2.自定義auth_user表

在models.py文件中配置 #1.導入模塊
from django.contrib.auth.models import AbstractUser #2.建表 # 第二種方式 使用類的繼承
class Userinfo(AbstractUser): # 千萬不要跟原來表中的字段重複 只能創新
    phone = models.BigIntegerField() avatar = models.CharField(max_length=32) #3.必定要在配置文件settings.py中告訴django orm再也不使用auth默認的表 而是使用你自定義的表
AUTH_USER_MODEL = 'app01.Userinfo'  # '應用名.類名'

#4.1.執行數據庫遷移命令,全部的auth模塊功能 所有都基於你建立的表 ,而再也不使用auth_user

五 settings功能插拔式源碼

#start.py
import notify notify.send_all('國慶放假了 記住放八天哦') #settings.py
NOTIFY_LIST = [ 'notify.email.Email', 'notify.msg.Msg', # 'notify.wechat.WeChat',
    'notify.qq.QQ', ] #_init_
import settings import importlib def send_all(content): for path_str in settings.NOTIFY_LIST:  # 1.拿出一個個的字符串 'notify.email.Email'
        module_path,class_name = path_str.rsplit('.',maxsplit=1)  # 2.從右邊開始 按照點切一個 ['notify.email','Email']
        module = importlib.import_module(module_path)  # from notity import msg,email,wechat
        cls = getattr(module,class_name)  # 利用反射 一切皆對象的思想 從文件中獲取屬性或者方法 cls = 一個個的類名
        obj = cls()  # 類實例化生成對象
        obj.send(content)  # 對象調方法

# class Email(object): def __init__(self): pass  # 發送郵件須要的代碼配置

    def send(self,content): print('郵件通知:%s'%content) class Msg(object): def __init__(self): pass  # 發送短信須要的代碼配置

    def send(self,content): print('短信通知:%s' % content) class QQ(object): def __init__(self): pass  # 發送qq須要的代碼準備

    def send(self,content): print('qq通知:%s'%content) class WeChat(object): def __init__(self): pass  # 發送微信須要的代碼配置

    def send(self,content): print('微信通知:%s'%content)
View Code
相關文章
相關標籤/搜索