什麼是csrf:html
跨站請求僞造前端
就是一個釣魚網站,界面操做和真是的頁面如出一轍,當用戶操做轉帳功能的時候,轉帳數據也會發送到真實的後臺,可是其中用戶輸入的信息中對端帳戶可能會被修改掉,致使用戶確實轉帳了,可是錢卻轉給了別人。python
如何區分釣魚網站和正經網站?在正經網站返回頁面的時候,在form表單中偷偷塞一個特殊的字符串,後端記下該頁面對應的字符串的值,等用戶發post請求來的時候,我先去校驗特殊的字符串是否匹配ajax
如何去寫這個特殊的字符串呢?模版語法有一個固定的寫法{% csrf_token %},必須寫在form表單內django
瀏覽器查看改標籤的值,而且每次都在刷新。再來演示剛剛轉帳的示例後端
# 正常網站: #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>
實現效果:瀏覽器
在正常網站前端輸入信息正常打印:post
在不正常的網站前端輸入信息:網站
在正常網站後端查看打印信息:url
怎麼解決出現這樣的釣魚網站避免後臺接收到虛假網站的數據直接處理出現了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