1 """ 2 django中間件是django的門戶 3 1.請求來的時候須要先通過中間件才能到達真正的django後端 4 2.響應走的時候最後也須要通過中間件才能發送出去 5 6 django自帶七個中間件 7 """ 8 django請求生命週期流程圖 9 10 研究django中間件代碼規律 11 MIDDLEWARE = [ 12 'django.middleware.security.SecurityMiddleware', 13 'django.contrib.sessions.middleware.SessionMiddleware', 14 'django.middleware.common.CommonMiddleware', 15 'django.middleware.csrf.CsrfViewMiddleware', 16 'django.contrib.auth.middleware.AuthenticationMiddleware', 17 'django.contrib.messages.middleware.MessageMiddleware', 18 'django.middleware.clickjacking.XFrameOptionsMiddleware', 19 ] 20 21 class SessionMiddleware(MiddlewareMixin): 22 def process_request(self, request): 23 session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME) 24 request.session = self.SessionStore(session_key) 25 def process_response(self, request, response): 26 return response 27 28 class CsrfViewMiddleware(MiddlewareMixin): 29 def process_request(self, request): 30 csrf_token = self._get_token(request) 31 if csrf_token is not None: 32 # Use same token next time. 33 request.META['CSRF_COOKIE'] = csrf_token 34 def process_view(self, request, callback, callback_args, callback_kwargs): 35 return self._accept(request) 36 37 def process_response(self, request, response): 38 return response 39 40 class AuthenticationMiddleware(MiddlewareMixin): 41 def process_request(self, request): 42 request.user = SimpleLazyObject(lambda: get_user(request)) 43 """ 44 django支持程序員自定義中間件而且暴露給程序員五個能夠自定義的方法 45 1.必須掌握 46 process_request 47 48 process_response 49 2.瞭解便可 50 process_view 51 52 process_template_response 53 54 process_exception 55 """
1 """ 2 1.在項目名或者應用名下建立一個任意名稱的文件夾 3 2.在該文件夾內建立一個任意名稱的py文件 4 3.在該py文件內須要書寫類(這個類必須繼承MiddlewareMixin) 5 而後在這個類裏面就能夠自定義五個方法了 6 (這五個方法並非所有都須要書寫,用幾個寫幾個) 7 4.須要將類的路徑以字符串的形式註冊到配置文件中才能生效 8 MIDDLEWARE = [ 9 'django.middleware.security.SecurityMiddleware', 10 'django.contrib.sessions.middleware.SessionMiddleware', 11 'django.middleware.common.CommonMiddleware', 12 'django.middleware.csrf.CsrfViewMiddleware', 13 'django.contrib.auth.middleware.AuthenticationMiddleware', 14 'django.contrib.messages.middleware.MessageMiddleware', 15 'django.middleware.clickjacking.XFrameOptionsMiddleware', 16 '你本身寫的中間件的路徑1', 17 '你本身寫的中間件的路徑2', 18 '你本身寫的中間件的路徑3', 19 ] 20 21 """ 22 23 ''' 24 from django.utils.deprecation import MiddlewareMixin 25 from django.shortcuts import render, HttpResponse, redirect 26 27 28 class MyMiddleware1(MiddlewareMixin): 29 def process_request(self, request): 30 print('第一個自定的process_request方法') 31 # return HttpResponse('第一個自定的process_request方法') 32 33 def process_response(self, request, response): 34 print('第一個自定的process_response方法') 35 return response 36 37 def process_view(self, request, view_name, *args, **kwargs): 38 print(view_name, args, kwargs) 39 print('第一個自定的process_view方法') 40 41 def process_template_response(self, request, response): 42 print('第一個自定的process_template_response方法') 43 return response 44 45 def process_exception(self, request, exception): 46 print('第一個自定的process_exception方法') 47 print(exception) 48 49 50 class MyMiddleware2(MiddlewareMixin): 51 def process_request(self, request): 52 print('第二個自定的process_request方法') 53 54 def process_response(self, request, response): 55 print('第二個自定的process_response方法') 56 return response 57 58 def process_view(self, request, view_name, *args, **kwargs): 59 print(view_name, args, kwargs) 60 print('第二個自定的process_view方法') 61 62 def process_template_response(self, request, response): 63 print('第二個自定的process_template_response方法') 64 return response 65 66 def process_exception(self, request, exception): 67 print('第二個自定的process_exception方法') 68 print(exception) 69 ''' 70 71 """ 72 1.必須掌握 73 process_request 74 1.請求來的時候須要通過每個中間件裏面的process_request方法 75 結果的順序是按照配置文件中註冊的中間件從上往下的順序依次執行 76 2.若是中間件裏面沒有定義該方法,那麼直接跳過執行下一個中間件 77 3.若是該方法返回了HttpResponse對象,那麼請求將再也不繼續日後執行 78 而是直接原路返回(校驗失敗不容許訪問...) 79 process_request方法就是用來作全局相關的全部限制功能 80 81 process_response (它的參數response就是django返回給瀏覽器的內容) 82 1.響應走的時候須要通過每個中間件裏面的process_response方法 83 該方法有兩個額外的參數request,response 84 2.該方法必須返回一個HttpResponse對象 85 1.默認返回的就是形參response 86 2.你也能夠本身返回本身的 87 3.順序是按照配置文件中註冊了的中間件從下往上依次通過 88 若是你沒有定義的話 直接跳過執行下一個 89 90 研究若是在第一個process_request方法就已經返回了HttpResponse對象,那麼響應走的時候是通過全部的中間件裏面的process_response仍是有其餘狀況 91 是其餘狀況 92 就是會直接走同級別的process_reponse返回 93 94 flask框架也有一箇中間件可是它的規律 95 只要返回數據了就必須通過全部中間件裏面的相似於process_reponse方法 96 97 98 2.瞭解便可 99 process_view 100 路由匹配成功以後執行視圖函數以前,會自動執行中間件裏面的該放法 101 順序是按照配置文件中註冊的中間件從上往下的順序依次執行 102 103 process_template_response 104 返回的HttpResponse對象有render屬性的時候纔會觸發 105 只要形參中有response你就必須返回 106 順序是按照配置文件中註冊了的中間件從下往上依次通過 107 ''' 108 def index(request): 109 print('在下index是也') 110 obj = HttpResponse('在下index是也') 111 def render(): 112 print('內部render方法') 113 return HttpResponse('98K牛逼') 114 obj.render = render 115 return obj 116 ''' 117 118 process_exception 119 當視圖函數中出現異常的狀況下觸發 120 參數exception就是報錯信息 121 順序是按照配置文件中註冊了的中間件從下往上依次通過 122 """ 123
1 """ 2 釣魚網站 3 我搭建一個跟正規網站如出一轍的界面(中國銀行) 4 用戶不當心進入到了咱們的網站,用戶給某我的打錢 5 打錢的操做確確實實是提交給了中國銀行的系統,用戶的錢也確確實實減小了 6 可是惟一不一樣的時候打錢的帳戶不適用戶想要打的帳戶變成了一個莫名其妙的帳戶 7 8 大學英語四六級 9 考以前須要學生本身網站登錄繳費 10 11 內部本質 12 咱們在釣魚網站的頁面 針對對方帳戶 只給用戶提供一個沒有name屬性的普通input框 13 而後咱們在內部隱藏一個已經寫好name和value的input框 14 15 如何規避上述問題 16 csrf跨站請求僞造校驗 17 網站在給用戶返回一個具備提交數據功能頁面的時候會給這個頁面加一個 18 惟一標識 19 當這個頁面朝後端發送post請求的時候 個人後端會先校驗惟一標識,若是 20 惟一標識不對直接拒絕(403 forbbiden)若是成功則正常執行 21 """
1 # form表單如何符合校驗 2 <form action="" method="post"> 3 {% csrf_token %} 4 <p>username:<input type="text" name="username"></p> 5 <p>target_user:<input type="text" name="target_user"></p> 6 <p>money:<input type="text" name="money"></p> 7 <input type="submit"> 8 </form> 9 10 # ajax如何符合校驗 11 // 第一種 利用標籤查找獲取頁面上的隨機字符串 12 {#data:{"username":'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},#} 13 // 第二種 利用模版語法提供的快捷書寫 14 {#data:{"username":'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#} 15 // 第三種 通用方式直接拷貝js代碼並應用到本身的html頁面上便可 16 {% load static %} 17 <script src="{% static 'js/mysetup.js'%}"></script>
1 function getCookie(name) { 2 var cookieValue = null; 3 if (document.cookie && document.cookie !== '') { 4 var cookies = document.cookie.split(';'); 5 for (var i = 0; i < cookies.length; i++) { 6 var cookie = jQuery.trim(cookies[i]); 7 // Does this cookie string begin with the name we want? 8 if (cookie.substring(0, name.length + 1) === (name + '=')) { 9 cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 10 break; 11 } 12 } 13 } 14 return cookieValue; 15 } 16 var csrftoken = getCookie('csrftoken'); 17 18 19 function csrfSafeMethod(method) { 20 // these HTTP methods do not require CSRF protection 21 return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 22 } 23 24 $.ajaxSetup({ 25 beforeSend: function (xhr, settings) { 26 if (!csrfSafeMethod(settings.type) && !this.crossDomain) { 27 xhr.setRequestHeader("X-CSRFToken", csrftoken); 28 } 29 } 30 });
1 """ 2 1.網站總體都不校驗csrf,就單單幾個視圖函數須要校驗 3 2.網站總體都校驗csrf,就單單幾個視圖函數不校驗 4 """ 5 from django.views.decorators.csrf import csrf_protect,csrf_exempt 6 from django.utils.decorators import method_decorator 7 """ 8 csrf_protect 須要校驗 9 針對csrf_protect符合咱們以前所學的裝飾器的三種玩法 10 csrf_exempt 忽視校驗 11 針對csrf_exempt只能給dispatch方法加纔有效 12 """ 13 # @csrf_exempt 14 # @csrf_protect 15 def transfer(request): 16 if request.method == 'POST': 17 username = request.POST.get('username') 18 target_user = request.POST.get('target_user') 19 money = request.POST.get('money') 20 print('%s給%s轉了%s元'%(username,target_user,money)) 21 return render(request,'transfer.html') 22 23 24 25 from django.views import View 26 27 # @method_decorator(csrf_protect,name='post') # 針對csrf_protect 第二種方式能夠 28 # @method_decorator(csrf_exempt,name='post') # 針對csrf_exempt 第二種方式不能夠 29 @method_decorator(csrf_exempt,name='dispatch') 30 class MyCsrfToken(View): 31 # @method_decorator(csrf_protect) # 針對csrf_protect 第三種方式能夠 32 # @method_decorator(csrf_exempt) # 針對csrf_exempt 第三種方式能夠 33 def dispatch(self, request, *args, **kwargs): 34 return super(MyCsrfToken, self).dispatch(request,*args,**kwargs) 35 36 def get(self,request): 37 return HttpResponse('get') 38 39 # @method_decorator(csrf_protect) # 針對csrf_protect 第一種方式能夠 40 # @method_decorator(csrf_exempt) # 針對csrf_exempt 第一種方式不能夠 41 def post(self,request): 42 return HttpResponse('post')
1 # 模塊:importlib 2 import importlib 3 res = 'myfile.b' 4 ret = importlib.import_module(res) # from myfile import b 5 # 該方法最小隻能到py文件名,不能再往下到文件裏邊變量名 6 print(ret) # <module 'myfile.b' from 'C:\\Users\\Administrator\\PycharmProjects\\day70\\myfile\\b.py'>
1 import settings 2 import importlib 3 4 5 def send_all(content): 6 for path_str in settings.NOTIFY_LIST: # path_str是setting得NOTIFY_LIST列表中一個個的字符串 例如:'notify.email.Email' 7 module_path, class_name = path_str.rsplit('.', maxsplit=1) 8 # modult_path = 'notify.email' class_name = 'Email' 9 # 1.利用字符串導入模塊 10 module = importlib.import_module(module_path) # 這句話至關於: from notify import email 11 # 2.利用反射獲取類名 12 cls = getattr(module, class_name) # 這句話就能夠拿到 Email、QQ、Wechat 13 # 3.生成類的對象 14 obj = cls() 15 # 4.利用鴨子類型直接調用send方法 16 obj.send(content)
1 ----email.py文件---- 2 3 class Email(object): 4 def __init__(self): 5 pass # 發送郵箱須要得前期準備工做 6 7 def send(self, content): 8 print('郵箱通知:%s'%content) 9 10 11 ----msg.py文件---- 12 13 class Msg(object): 14 def __init__(self): 15 pass # 發送短信須要得前期準備工做 16 17 def send(self, content): 18 print('短信通知:%s'%content) 19 20 ----wechat.py文件---- 21 22 class Wechat(object): 23 def __init__(self): 24 pass # 發送微信須要得前期準備工做 25 26 def send(self, content): 27 print('微信通知:%s'%content) 28 29 ----qq.py文件---- 30 31 class QQ(object): 32 def __init__(self): 33 pass # 發送QQ須要得前期準備工做 34 35 def send(self, content): 36 print('QQ通知:%s'%content)
1 NOTIFY_LIST = [ 2 'notify.email.Email', 3 'notify.qq.QQ', 4 'notify.wechat.Wechat', 5 'notify.msg.Msg', 6 ]
1 import notify 2 3 notify.send_all('快線上開課了') 4 5 # 執行結果 6 ''' 7 郵箱通知:快線上開課了 8 QQ通知:快線上開課了 9 微信通知:快線上開課了 10 短信通知:快線上開課了 11 '''
1 ''' 2 今日做業 3 1.整理今日內容至我的博客或筆記中 4 2.本身編寫參考django中間件實現功能可配置插拔式設計體會編程思想 5 '''