1、什么是csrf
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性;
可以这样来理解:
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,
比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
举例子说明csrf攻击流程:
黑客做了和银行系统一样的钓鱼网站,但其实已经对内部信息做了篡改,用户在不知道的情况下打开了这个钓鱼网站,登录并且转账,
用户点击提交后,钓鱼网站就会向真正的银行系统接口提交用户的信息,银行系统并不知道这个信息是黑客提交的,就会进行转账操作;
或者黑客利用cookie来实施csrf攻击,比如你登录了一个真的银行网站,但你在没有退出登陆的情况下又点开了一个钓鱼网站,
这个钓鱼网站要求用户发一个转账请求,此时用户并不知情,就携带着cookie发了一个转账请求,银行系统同样不知道这个信息是黑客提交的,就会进行转账操作;
2、Django前端防止csrf攻击的方法
防止csrf攻击的策略:
当用户访问一个网站时,网站会返回一大串字符串,用户数据提交给服务器后,那串字符串也会一起提交,
网站会验证字符串的正确性,而且字符串是随时变化的,只要网页一刷新,字符串就会更新;
settings.py中 'django.middleware.csrf.CsrfViewMiddleware', 这个中间件不要注释掉;
方式一:在form表单中应用:
<form action="" method="post"> {% csrf_token %} <!--写上这一句即可--> <p>用户名:<input type="text" name="name"></p> <p>密码:<input type="text" name="password"></p> <p><input type="submit"></p> </form>
方式二:在ajax中应用,也就是手动获取到字符串的value值(同一个页面可以获取),django中name="csrfmiddlewaretoken"是固定的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </head> <body> <h3>正常网站</h3> <!--form表单验证csrf问题--> <form action="" method="post"> {% csrf_token %} <p>username: <input type="text" name="username"></p> <p>money: <input type="text" name="money"></p> <p>others: <input type="text" name="others"></p> <input type="submit"> </form> <!--ajax表单验证csrf问题--> <button>ajax</button> </body> <script> $('button').click(function () { $.ajax({ url:'', type:'post', <!--ajax 方式--> data:{'name': 'jason', 'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()}, success:function (data) { console.log(data) } }) }) </script> </html>
3、后端操作csrf
比如当全局开启csrf验证时,有某个页面不需要验证:
views.py
# 需要导入以下模块 from django.views.decorators.csrf import csrf_exempt, csrf_protect # 不再检测(全站使用时) @csrf_exempt def csrf_token(request):# if request.method=='POST': print(request.POST) return HttpResponse('ok') return render(request,'csrf_token.html')
比如当全局禁用csrf验证时,有某个页面需要验证:
views.py
# 需要导入以下模块 from django.views.decorators.csrf import csrf_exempt, csrf_protect # 检测(全站禁用时) @csrf_protect def csrf_token(request):# if request.method=='POST': print(request.POST) return HttpResponse('ok') return render(request,'csrf_token.html')
在CBV中使用:
# 先导模块 from django.utils.decorators import method_decorator # 当全局禁用csrf时,也就是把那个中间件注释掉了,使用方法和CBV验证session时装饰器的用法一样(三种), https://www.cnblogs.com/weiyiming007/p/12401218.html # 当全局启用csrf时,也就是把那个中间件没有注释掉,只能有下面两种方式,其实都是给dispatch加 @method_decorator(csrf_exempt,name='dispatch') # 第一种 class Index3(View): # @method_decorator(csrf_exempt) # 第二种 def dispatch(self, request, *args, **kwargs): super().dispatch(request,*args,**kwargs)