什么是csrf:
跨站請求偽造
就是一個釣魚網站,界面操作和真是的頁面一模一樣,當用戶操作轉賬功能的時候,轉賬數據也會發送到真實的后台,但是其中用戶輸入的信息中對端賬戶可能會被修改掉,導致用戶確實轉賬了,但是錢卻轉給了別人。
如何區分釣魚網站和正經網站?在正經網站返回頁面的時候,在form表單中偷偷塞一個特殊的字符串,后端記下該頁面對應的字符串的值,等用戶發post請求來的時候,我先去校驗特殊的字符串是否匹配
如何去寫這個特殊的字符串呢?模版語法有一個固定的寫法{% csrf_token %},必須寫在form表單內
瀏覽器查看改標簽的值,並且每次都在刷新。再來演示剛剛轉賬的示例
# 正常網站: #views # Create your views here. def transfer(request): if request.method=='POST': username=request.POST.get('username') to_username=request.POST.get('to_username') monery=request.POST.get('monery') print(username,to_username,monery) return render(request,'transfer.html')
<body> <h1>正經網站</h1> <form action="" method="post"> <p>賬戶名:<input type="text" name="username"></p> <p>對方賬戶:<input type="text" name="to_username"></p> <p>轉賬金額:<input type="text" name="monery"></p> <input type="submit"> </form> </body>
# 不正常網站 #views: def transfer(request): return render(request,'transfer.html')
<body> <h1>釣魚網站</h1> <form action="http://127.0.0.1:8000/transfer/" method="post"> <p>賬戶名:<input type="text" name="username"></p> <p>對方賬戶:<input type="text"></p> <p>轉賬金額:<input type="text" name=monery></p> <input type="text" name="to_username" value="yzn" style="display: none" > # 定義一個隱藏標簽 <input type="submit"> </form> </body>
實現效果:
在正常網站前端輸入信息正常打印:
在不正常的網站前端輸入信息:
在正常網站后端查看打印信息:
怎么解決出現這樣的釣魚網站避免后台接收到虛假網站的數據直接處理出現了csrf
在settings.py文件中把之前注釋的內容取消注釋
django.middleware.csrf.CsrfViewMiddleware
在前端設置一個csfr_token
<form action="" method="post"> {% csrf_token %} <p>賬戶名:<input type="text" name="username"></p> <p>對方賬戶:<input type="text" name="to_username"></p> <p>轉賬金額:<input type="text" name="monery"></p> <input type="submit"> </form>
查看前端頁面會隨機產生一個token值,頁面刷新就會差生新的token值
前端ajax避免前端出現csrf驗證問題:
<button>ajax</button> <script> $('button').click(function () { $.ajax({ url:'', type:'post', data:{'name':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()}, success:function (data) { console.log(data) } }) })
局部不需要csrf效驗
# viess.py
from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_exempt def index(request): return HttpResponse('ok')
# transfer.html <h1>正經網站</h1> <form action="/index/" method="post"> {# {% csrf_token %}#} #禁用csrf_token <p>賬戶名:<input type="text" name="username"></p> <p>對方賬戶:<input type="text" name="to_username"></p> <p>轉賬金額:<input type="text" name="monery"></p> <input type="submit"> </form>
結果可以訪問到OK;全局啟用,局部禁用
全局禁用,局部啟用
@csrf_protect def index(request): return HttpResponse('ok')
# 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