由django的生命週期圖咱們能夠看出,django的中間件就相似於django的保安,請求一個相應時要先經過中間件才能到達django後端(url、views、template、models),一樣後端進行響應的時候也須要通過中間件才能達到web服務網關。前端
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', # 一些安全設置,好比XSS腳本過濾 'django.contrib.sessions.middleware.SessionMiddleware', # session支持中間件,加入這個中間件,會在數據庫中生成一個django_session的表。 'django.middleware.common.CommonMiddleware', # 通用中間件,會處理一些URL,好比baidu.com會自動的處理成www.baidu.com。好比/blog/111會處理成/blog/111/自動加上反斜槓。 'django.middleware.csrf.CsrfViewMiddleware', # 跨域請求僞造中間件。加入這個中間件,在提交表單的時候會必須加入csrf_token,cookie中也會生成一個名叫csrftoken的值,也會在header中加入一個HTTP_X_CSRFTOKEN的值來放置CSRF攻擊。 'django.contrib.auth.middleware.AuthenticationMiddleware', # 用戶受權中間件。他會在每一個HttpRequest對象到達view以前添加當前登陸用戶的user屬性,也就是你能夠在view中經過request訪問user。 'django.contrib.messages.middleware.MessageMiddleware', # 消息中間件。展現一些後臺信息給前端頁面。若是須要用到消息,還須要在INSTALLED_APPS中添加django.contrib.message纔能有效。若是不須要,能夠把這兩個都刪除。 'django.middleware.clickjacking.XFrameOptionsMiddleware', # 防止經過瀏覽器頁面跨Frame出現clickjacking(欺騙點擊)攻擊出現。 ]
中間件能夠定義五個方法,分別是:(主要的是process_request和process_response)web
1.process_request()方法ajax
規律
1.請求來的時候 會通過每一箇中間件裏面的process_request方法(從上往下)
2.若是方法裏面直接返回了HttpResponse對象 那麼會直接返回 再也不往下執行
基於該特色就能夠作訪問頻率限制,身份校驗,權限校驗數據庫
2.process_response()方法django
規律
1.必須將response形參返回 由於這個形參指代的就是要返回給前端的數據
2.響應走的時候 會依次通過每個中間件裏面的process_response方法(從下往上)後端
3.process_view()方法跨域
1.在路由匹配成功執行視圖函數以前 觸發瀏覽器
4.process_exception()方法安全
1.當你的視圖函數報錯時 就會自動執行cookie
5.process_template_response()方法
1.當你返回的HttpResponse對象中必須包含render屬性纔會觸發
def index(request): print('我是index視圖函數') def render(): return HttpResponse('什麼鬼玩意') obj = HttpResponse('index') obj.render = render return obj
總結:以上方法的返回值能夠是None或一個HttpResponse對象,若是是None,則繼續按照django定義的規則向後繼續執行,若是是HttpResponse對象,則直接將該對象返回給用戶。
中間件的proce_request方法是在執行視圖函數以前執行的。
當配置多箇中間件時,會按照MIDDLEWARE中的註冊順序,也就是列表的索引值,從前到後依次執行的。
不一樣的中間件之間傳遞的request都是同一個對象。
若是須要本身寫的中間件生效,必須繼承MiddlewareMixin,並且要保證在註冊時路徑不能寫錯。
關於釣魚網站的原理,好比說你登陸了一個釣魚網站的頁面,和中國銀行如出一轍的頁面,你在哪裏進行轉帳操做,它的轉帳信息也確實發到了中國銀行,你的帳戶確實也扣錢了,可是惟一不對的時收款人不是你輸入的那我的,那是由於它在用戶輸入框的input上作了手腳,這個input沒有設置name屬性,而在內部,隱藏的標籤裏,有一個寫好了name和value的input框,這樣你只要點擊提交,那個value(釣魚網站受益人的帳戶)就會和你的轉帳信息一塊兒發給中國銀行。
網站會給返回給用戶的form表單頁面 偷偷塞一個隨機字符串
請求到來的時候 會先比對隨機字符串是否一致 若是不一致 直接拒絕(403)
該隨機字符串有如下特色
1.同一個瀏覽器每一次訪問都不同
2.不一樣瀏覽器絕對不會重複
1.form表單發送post請求的時候 須要你作得僅僅書寫一句話
{% csrf_token %}
2.ajax發送post請求 如何避免csrf校驗
1.如今頁面上寫{% csrf_token %},利用標籤查找 獲取到該input鍵值信息 {'username':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()} $('[name=csrfmiddlewaretoken]').val() 2.直接書寫'{{ csrf_token }}' {'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'} {{ csrf_token }} 3.你能夠將該獲取隨機鍵值對的方法 寫到一個js文件中,以後只須要導入該文件便可 新建一個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); } } });
防釣魚的處理方法有了,當若是你的網站全局都須要校驗csrf的時候,又有幾個不須要校驗的該如何處理,相反若是你的網站全局不須要校驗csrf的時候,又有幾個須要校驗的功能又該怎麼處理。
#先導入模塊 from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt,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')
總結:裝飾器中只有csrf_exempt是特例,其餘的裝飾器在給CBV裝飾的時候 均可以有三種方式
Auth模塊是Django自帶的用戶認證模塊:
咱們在開發一個網站的時候,無可避免的須要設計實現網站的用戶系統。此時咱們須要實現包括用戶註冊、用戶登陸、用戶認證、註銷、修改密碼等功能,這還真是個麻煩的事情呢。
Django做爲一個完美主義者的終極框架,固然也會想到用戶的這些痛點。它內置了強大的用戶認證系統--auth,它默認使用 auth_user 表來存儲用戶數據。
要注意的時,使用auth模塊的話最好用全套。
createsuperuser #建立超級用戶 這個超級用戶就能夠擁有登錄django admin後臺管理的權限
auth模塊的功能
#查詢用戶 from django.contrib import auth user_obj = auth.authenticate(username=username,password=password) # 必需要用 由於數據庫中的密碼字段是密文的 而你獲取的用戶輸入的是明文 #記錄用戶狀態 auth.login(request,user_obj) # 將用戶狀態記錄到session中 #判斷用戶是否登陸 print(request.user.is_authenticated) # 判斷用戶是否登陸 若是是大家用戶會返回False #用戶登陸以後 獲取用戶對象 print(request.user) # 若是沒有執行auth.login那麼拿到的是匿名用戶 #校驗用戶是否登陸 from django.contrib.auth.decorators import login_required @login_required(login_url='/xxx/') # 局部配置 def index(request): pass # 全局配置 settings文件中 LOGIN_URL = '/xxx/' #驗證密碼是否正確 request.user.check_password(old_password) #修改密碼 request.user.set_password(new_password) request.user.save() # 修改密碼的時候 必定要save保存 不然沒法生效 #退出登錄 auth.logout(request) # request.session.flush() #註冊用戶 # 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') # 建立超級用戶 郵箱必填
from django.contrib.auth.models import AbstractUser # Create your models here. # 第一種 使用一對一關係 不考慮 # 第二種方式 使用類的繼承 class Userinfo(AbstractUser): # 千萬不要跟原來表中的字段重複 只能創新 phone = models.BigIntegerField() avatar = models.CharField(max_length=32) # 必定要在配置文件中 告訴django # 告訴django orm再也不使用auth默認的表 而是使用你自定義的表 AUTH_USER_MODEL = 'app01.Userinfo' # '應用名.類名'
""" 1.執行數據庫遷移命令 全部的auth模塊功能 所有都基於你建立的表 而再也不使用auth_user """